Jestem nowy w Haskell i jestem bardzo zdezorientowany przez Where vs. Let . Wydaje się, że oba mają podobny cel. Przeczytałem kilka porównań między Where vs. Let, ale mam problem z rozróżnieniem, kiedy użyć każdego z nich. Czy ktoś mógłby podać jakiś kontekst lub może kilka przykładów, które pokazują, kiedy używać jednego nad drugim?
Gdzie vs. Let
where
Punkt może być określony tylko przy poziomie definicji funkcji. Zwykle jest to identyczne z zakresemlet
definicji. Jedyna różnica dotyczy sytuacji, w których używa się strażników . Zakreswhere
klauzuli obejmuje wszystkich strażników. W przeciwieństwie do tego zakreslet
wyrażenia to tylko bieżąca klauzula funkcji i ochrona, jeśli taka istnieje.
Haskell Wiki jest bardzo szczegółowy i zapewnia różne przypadki, ale używa hipotetycznych przykładów. Uważam, że jego wyjaśnienia są zbyt krótkie dla początkującego.
Zalety Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
nie zadziała, ponieważ gdzie odnosi się do wzorca pasującego do f =, gdzie nie ma x w zasięgu. Z drugiej strony, gdybyś zaczął od let, nie miałbyś problemów.
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Zalety miejsca :
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)
Wiki Haskell wspomina, że klauzula Where jest deklaratywna, podczas gdy wyrażenie Let jest ekspresyjne. Poza stylem, czym różnią się od siebie?
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 ...
- W pierwszym przykładzie, dlaczego zakres Let in but gdzie go nie ma?
- Czy można się zgłosić Gdzie do pierwszego przykładu?
- Czy ktoś może zastosować to do rzeczywistych przykładów, w których zmienne reprezentują rzeczywiste wyrażenia?
- Czy istnieje ogólna zasada, której należy przestrzegać, kiedy używać każdego z nich?
Aktualizacja
Dla tych, którzy przejdą przez ten wątek później, najlepsze wyjaśnienie znalazłem tutaj: „ Delikatne wprowadzenie do Haskella ”.
Niech wyrażenia.
Wyrażenia let Haskella są przydatne, gdy wymagany jest zagnieżdżony zestaw powiązań. Jako prosty przykład rozważ:
let y = a*b f x = (x+y)/y in f c + f d
Zestaw powiązań utworzonych przez wyrażenie let jest wzajemnie rekurencyjny, a powiązania wzorców są traktowane jako leniwe wzorce (tj. Zawierają niejawne ~). Jedynym dozwolonym rodzajem deklaracji są podpisy typów, powiązania funkcji i powiązania wzorców.
Gdzie klauzule.
Czasami wygodnie jest określić zakres powiązań dla kilku chronionych równań, co wymaga klauzuli where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Zauważ, że nie można tego zrobić za pomocą wyrażenia let, które ogranicza się tylko do wyrażenia, które zawiera. Klauzula where jest dozwolona tylko na najwyższym poziomie zestawu równań lub wyrażenia przypadku. Te same właściwości i ograniczenia dotyczące powiązań w wyrażeniach let mają zastosowanie do tych w klauzulach where. Te dwie formy zasięgu zagnieżdżonego wydają się bardzo podobne, ale pamiętaj, że wyrażenie let jest wyrażeniem, podczas gdy klauzula where nie jest - jest częścią składni deklaracji funkcji i wyrażeń wielkości liter.
f = body where x = xbody; y = ybody ...
oznaczaf = let x = xbody; y = ybody ... in body
case .... of ... where
jakoś przekształcić wyrażenie let w wyrażenie? Nie jestem tego pewien.
let
iwhere
kiedy zacząłem się uczyć Haskella. Myślę, że najlepszym sposobem, aby to zrozumieć, jest uświadomienie sobie, że między nimi jest bardzo niewielka różnica, a zatem nie ma się czym martwić. Znaczeniewhere
podane w kategoriachlet
bardzo prostej mechanicznej transformacji. Zobacz haskell.org/onlinereport/decls.html#sect4.4.3.2 Ta transformacja istnieje tak naprawdę tylko dla wygody notacji.