Thành phần hàm Haskell (.) Và thành ngữ ứng dụng ($): sử dụng đúng


129

Tôi đã đọc Real World Haskell , và tôi sắp kết thúc, nhưng một vấn đề về phong cách đã gây khó chịu cho tôi để làm với (.)($) khai thác.

Khi bạn viết một hàm là một thành phần của các hàm khác, bạn viết nó như sau:

f = g . h

Nhưng khi bạn áp dụng một cái gì đó vào cuối các chức năng đó, tôi viết nó như thế này:

k = a $ b $ c $ value

Nhưng cuốn sách sẽ viết nó như thế này:

k = a . b . c $ value

Bây giờ, với tôi trông chúng có chức năng tương đương, chúng làm điều tương tự trong mắt tôi. Tuy nhiên, càng nhìn, tôi càng thấy mọi người viết các chức năng của họ theo cách mà cuốn sách thực hiện: sáng tác (.)trước và sau đó chỉ sử dụng cuối cùng ($)để thêm một giá trị để đánh giá lô (không ai làm với nhiều tác phẩm bằng đô la) .

Có một lý do cho việc sử dụng các cách sách tốt hơn nhiều so với việc sử dụng tất cả các ($)biểu tượng? Hoặc có một số thực hành tốt nhất ở đây mà tôi không nhận được? Hay nó là thừa và tôi không nên lo lắng về nó?


4
Lưu ý rằng ví dụ thứ hai có thể được thực hiện nhưk = a $ b $ c value
Thomas Eding

1
Vâng, có thể, như Zifre đã đề cập dưới đây, nhưng tôi đã quyết định để nó ở đó vì nó không gây hại gì và làm cho ý kiến ​​của anh ấy (và bây giờ của bạn) có ý nghĩa. Cảm ơn bạn mặc dù. +1 :)
Robert Massaioli

2
Một cách tiếp cận phổ biến khác là a . b $ c value, tôi không thích nhiều như ví dụ thứ ba nhưng lưu một vài ký tự.
John L

Câu trả lời:


153

Tôi đoán tôi có thể trả lời điều này từ chính quyền.

Có lý do nào để sử dụng cách sách tốt hơn nhiều so với sử dụng tất cả các ký hiệu ($) không?

Không có lý do đặc biệt. Bryan và tôi đều thích giảm tiếng ồn đường truyền. .yên tĩnh hơn $. Kết quả là cuốn sách sử dụng f . g . h $ xcú pháp.


3
Chà, tôi không thể hy vọng câu trả lời hay hơn câu này; từ một trong những tác giả :) Và điều đó có ý nghĩa, nó trông yên tĩnh hơn nhiều trên trang khi tôi đọc. Đánh dấu đây là câu trả lời vì Nó trực tiếp trả lời câu hỏi. Cảm ơn bạn đã phản hồi; và, nguyên vẹn, cuốn sách.
Robert Massaioli

38
Không đồng ý với tác giả, nhưng tôi nghĩ có một lý do khác nổi bật hơn trong mô hình tinh thần của việc tạo ra một cái gì đó hơn là sử dụng nó. Người dùng Haskell có xu hướng muốn nghĩ về f.g.hmột sáng tạo thông minh mới hơn f(g(h())). Bây giờ họ đang gọi một hàm mới, mặc dù ẩn danh, mà họ đã tạo thay vì chỉ tạo ra một từ điển lớn các lệnh gọi hàm sẵn như người dùng PHP.
Evan Carroll

1
Đó là một tuyên bố thú vị: 'giảm tiếng ồn đường truyền' và 'yên tĩnh hơn'. Tôi chưa bao giờ nghĩ về ngôn ngữ lập trình theo thuật ngữ này, nhưng nó có ý nghĩa hoàn hảo.
Rabarberski

53

Chúng thực sự tương đương nhau: Hãy nhớ rằng người $vận hành, về cơ bản, không có gì. f $ xđánh giá để f x. Mục đích của $hành vi cố định của nó: quyền ưu tiên liên kết và tối thiểu. Xóa $và sử dụng dấu ngoặc đơn để nhóm thay vì ưu tiên infix, đoạn mã trông như thế này:

k = a (b (c (value)))

k = (a . b . c) value

Lý do thích .phiên bản hơn $phiên bản là lý do tương tự cho việc thích cả hai so với phiên bản được ngoặc đơn ở trên: sự hấp dẫn về mặt thẩm mỹ.

Mặc dù, một số người có thể tự hỏi liệu việc sử dụng toán tử infix thay cho dấu ngoặc đơn có dựa trên một sự thôi thúc tiềm thức nào đó để tránh bất kỳ sự giống nhau nào có thể xảy ra với Lisp (chỉ đùa thôi ... tôi nghĩ sao?).


38

Tôi muốn thêm nó vào f . g $ x, f . glà một đơn vị cú pháp có ý nghĩa.

Trong khi đó, trong f $ g $ x, f $ gkhông phải là một đơn vị có ý nghĩa. Một chuỗi $được cho là bắt buộc hơn - đầu tiên nhận được kết quả gcủa x, sau đó làm fcho nó, sau đó làm foocho nó, sau đó vv

Trong khi đó, một chuỗi .được cho là khai báo nhiều hơn, và theo một nghĩa nào đó gần hơn với một khung nhìn trung tâm dataflow - soạn một loạt các hàm, và cuối cùng áp dụng chúng vào một cái gì đó.


2
Tôi đang học Haskell (chưa mã hóa bất cứ điều gì có ý nghĩa) nhưng tôi thích nghĩ về $ như một loại toán tử "ống". Nó rất giống với thiết bị đầu cuối | ống (ngoại trừ luồng dữ liệu từ phải sang trái), nhưng giống như các quá trình đầu cuối, mỗi đơn vị độc lập rõ ràng.
LostSalad

1
Các $nhà điều hành dường như cư xử tương tự như các <|nhà điều hành trong F #. Tôi tin rằng cả hai đều được định nghĩa giống nhau, trên thực tế - trong F # (<|) a b = a bvà trong Haskell, a $ b = a bvề cơ bản là tương đương.
Tom Galvin

@Quackmatic Khá chắc chắn là (<|) b a = a btrong F #, vì nó được sử dụng như thế [1; 2; 3; 4; 5] <| List.map ((+) 1), nếu bộ nhớ phục vụ.
BalinKingOfMoria Tái lập CM

@BalinKingOfMoria <|Toán tử chuyển giá trị cho hàm, thay vì truyền hàm cho giá trị - ví dụ mã của bạn sẽ hoạt động với |>toán tử, thay vào đó.
Tom Galvin

@Quackmatic ơi. Không biết có nhiều phiên bản (Tôi chưa sử dụng F # rất nhiều).
BalinKingOfMoria Phục hồi CM

18

Đối với tôi, tôi nghĩ câu trả lời là (a) sự gọn gàng, như Don đã nói ; và (b) Tôi thấy rằng khi tôi chỉnh sửa mã, chức năng của tôi có thể kết thúc theo kiểu không có điểm, và sau đó, tất cả những gì tôi phải làm là xóa cái cuối cùng $thay vì quay lại và thay đổi mọi thứ. Một điểm nhỏ, chắc chắn, nhưng tốt đẹp.


Vâng đó là một lý do tốt để viết nó như vậy, nếu bạn muốn kết thúc trong một thành phần chức năng thì nó nhanh hơn. :) Yay để lưu tổ hợp phím, nhưng quan trọng hơn là thời gian. +1
Robert Massaioli

13

Có một cuộc thảo luận thú vị về câu hỏi này về chủ đề haskell-cafe này . Rõ ràng có một quan điểm thiểu số mà chủ trương rằng associativity phải $"chỉ đơn giản sai" , và chọn f . g . h $ xtrên f $ g $ h $ xlà một cách để phụ bước vấn đề này.


Này, bạn đã tìm thấy cả một cuộc thảo luận về vấn đề này. Điều đó thật tuyệt vời, tôi đang đọc ngay bây giờ. +1
Robert Massaioli

2
Đối số tương tự ở đây: ghc.haskell.org/trac/haskell-prime/wiki/iêu
enrique

Lưu ý rằng $!cũng có sự kết hợp đúng "sai hoàn toàn" - Tại sao lại là $! Nhà điều hành phải liên kết? .
imz - Ivan Zakharyaschev 7/07/2015

3

Đó chỉ là vấn đề về phong cách. Tuy nhiên, cách cuốn sách làm nó có ý nghĩa hơn với tôi. Nó tổng hợp tất cả các hàm, và sau đó áp dụng nó cho giá trị.

Phương pháp của bạn trông lạ, và cuối cùng $ là không cần thiết.

Tuy nhiên, nó thực sự không quan trọng. Trong Haskell, thường có rất nhiều, rất nhiều cách chính xác để làm điều tương tự.


3
Tôi đã không nhận thấy rằng $ cuối cùng là không cần thiết nhưng tôi nên có. Cảm ơn và tôi sẽ để nó ở đó để mọi người biết ý kiến ​​này có nghĩa gì.
Robert Massaioli

0

Tôi nhận ra đây là một câu hỏi rất cũ, nhưng tôi nghĩ có một lý do khác cho việc này chưa được đề cập.

Nếu bạn đang khai báo một hàm không có điểm mới f . g . h, giá trị bạn chuyển vào sẽ tự động được áp dụng. Tuy nhiên, nếu bạn viết f $ g $ h, nó sẽ không hoạt động.

Tôi nghĩ lý do tác giả thích phương pháp sáng tác là vì nó dẫn đến một thực tiễn tốt về xây dựng các chức năng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.