Tôi mới sử dụng Haskell và tôi rất bối rối trước Where vs. Let . Cả hai dường như cung cấp một mục đích tương tự. Tôi đã đọc một số so sánh giữa Where và Let nhưng tôi gặp khó khăn khi phân biệt khi nào sử dụng mỗi. Ai đó có thể vui lòng cung cấp một số ngữ cảnh hoặc có lẽ một vài ví dụ chứng minh khi nào sử dụng cái này thay cho cái kia không?
Where vs. Let
Một
where
mệnh đề chỉ có thể được định nghĩa ở cấp độ của một định nghĩa hàm. Thông thường, điều đó giống với phạm vilet
định nghĩa. Sự khác biệt duy nhất là khi các vệ sĩ được sử dụng . Phạm vi củawhere
điều khoản mở rộng trên tất cả các vệ sĩ. Ngược lại, phạm vi của mộtlet
biểu thức chỉ là mệnh đề chức năng hiện tại và bảo vệ, nếu có.
Các Haskell Wiki là rất chi tiết và cung cấp các trường hợp khác nhau nhưng nó sử dụng ví dụ giả thuyết. Tôi thấy những lời giải thích của nó quá ngắn gọn cho một người mới bắt đầu.
Ưu điểm của Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
sẽ không hoạt động, bởi vì nơi đề cập đến mẫu khớp f =, nơi không có x trong phạm vi. Ngược lại, nếu bạn đã bắt đầu với let, thì bạn sẽ không gặp khó khăn.
Haskell Wiki về Ưu điểm của Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Ưu điểm ở đâu :
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
f x
= let a = w x
in case () of
_ | cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
Haskell wiki đề cập rằng mệnh đề Where là khai báo trong khi biểu thức Let là biểu cảm. Ngoài phong cách, chúng hoạt động khác nhau như thế nào?
Declaration style | Expression-style
--------------------------------------+---------------------------------------------
where clause | let expression
arguments LHS: f x = x*x | Lambda abstraction: f = \x -> x*x
Pattern matching: f [] = 0 | case expression: f xs = case xs of [] -> 0
Guards: f [x] | x>0 = 'a' | if expression: f [x] = if x>0 then 'a' else ...
- Trong ví dụ đầu tiên, tại sao phạm vi Let in nhưng Where không?
- Có thể áp dụng Where cho ví dụ đầu tiên không?
- Một số có thể áp dụng điều này cho các ví dụ thực tế trong đó các biến đại diện cho các biểu thức thực tế không?
- Có nguyên tắc chung nào cần tuân theo khi sử dụng từng loại không?
Cập nhật
Đối với những người theo chủ đề này sau này, tôi tìm thấy lời giải thích tốt nhất ở đây: " Giới thiệu nhẹ nhàng về Haskell ".
Hãy biểu thức.
Biểu thức let của Haskell hữu ích bất cứ khi nào yêu cầu một tập hợp các ràng buộc lồng nhau. Như một ví dụ đơn giản, hãy xem xét:
let y = a*b f x = (x+y)/y in f c + f d
Tập hợp các ràng buộc được tạo bởi một biểu thức let là đệ quy lẫn nhau và các liên kết mẫu được coi là các mẫu lười (tức là chúng mang một dấu ~ ngầm định). Loại khai báo duy nhất được phép là chữ ký kiểu, liên kết hàm và liên kết mẫu.
Điều khoản ở đâu.
Đôi khi, rất thuận tiện để xác định phạm vi ràng buộc qua một số phương trình được bảo vệ, điều này yêu cầu mệnh đề where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Lưu ý rằng điều này không thể được thực hiện với biểu thức let, biểu thức này chỉ bao gồm biểu thức mà nó bao gồm. Mệnh đề where chỉ được phép ở cấp cao nhất của một tập phương trình hoặc biểu thức trường hợp. Các thuộc tính và ràng buộc giống nhau về ràng buộc trong biểu thức let áp dụng cho các thuộc tính trong mệnh đề where. Hai dạng phạm vi lồng nhau này có vẻ rất giống nhau, nhưng hãy nhớ rằng biểu thức let là một biểu thức, trong khi mệnh đề where thì không - nó là một phần của cú pháp khai báo hàm và biểu thức trường hợp.
f = body where x = xbody; y = ybody ...
có nghĩa làf = let x = xbody; y = ybody ... in body
case .... of ... where
biểu thức bằng cách nào đó không? Tôi không chắc chắn về điều này.
let
vàwhere
khi tôi lần đầu tiên bắt đầu học Haskell. Tôi nghĩ cách tốt nhất để hiểu nó là nhận ra rằng có rất ít sự khác biệt giữa hai điều này, và do đó không có gì phải lo lắng. Ý nghĩa củawhere
được cho về mặtlet
thông qua một phép biến đổi cơ học rất đơn giản. Thực ra, hãy xem haskell.org/onlinereport/decls.html#sect4.4.3.2 Sự chuyển đổi này chỉ tồn tại vì sự tiện lợi về mặt ký hiệu.