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.
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.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.Odpowiedzi:
1: Problem w przykładzie
jest parametrem
x
. Rzeczy wwhere
klauzuli mogą odnosić się tylko do parametrów funkcjif
(nie ma ich) i rzeczy w zewnętrznych zakresach.2: Aby użyć a
where
w pierwszym przykładzie, możesz wprowadzić drugą nazwaną funkcję, która przyjmujex
parametr jako parametr, na przykład:lub tak:
3: Oto pełny przykład bez
...
znaków:4: Kiedy używać
let
lubwhere
zależy od gustu. Używamlet
do podkreślenia obliczeń (przesuwając je do przodu) iwhere
do podkreślenia przepływu programu (przesuwając obliczenia do tyłu).źródło
Chociaż istnieje różnica techniczna w odniesieniu do strażników, na którą zwrócił uwagę Ephemient, istnieje również różnica pojęciowa w tym, czy chcesz umieścić główną formułę z góry z dodatkowymi zmiennymi zdefiniowanymi poniżej (
where
), czy też chcesz zdefiniować wszystko z góry i umieścić wzór poniżej (let
). Każdy styl ma inny akcent i widać, że oba są używane w pracach matematycznych, podręcznikach itp. Ogólnie, zmienne, które są na tyle nieintuicyjne, że wzór nie ma sensu bez nich, powinny być zdefiniowane powyżej; zmienne, które są intuicyjne ze względu na kontekst lub ich nazwy, należy zdefiniować poniżej. Na przykład w przykładzie hasVowel firmy Ephemient znaczenievowels
jest oczywiste, więc nie trzeba go definiować powyżej jego użycia (pomijając fakt,let
że nie zadziała ze względu na ochronę).źródło
Prawny:
Nielegalne:
Prawny:
Niedopuszczalne: (w przeciwieństwie do ML)
źródło
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
to nowa linia)Ten przykład z LYHFGG okazał się pomocny:
let
jest wyrażeniem, więc możesz wstawićlet
dowolne (!) miejsce, do którego mogą się udać wyrażenia.Innymi słowy, w powyższym przykładzie nie można
where
po prostu zastąpićlet
(być może bez użycia bardziej rozwlekłegocase
wyrażenia w połączeniu zwhere
).źródło
Niestety, większość odpowiedzi tutaj jest zbyt technicznych dla początkującego.
LHYFGG ma na ten temat odpowiedni rozdział - który powinieneś przeczytać, jeśli jeszcze tego nie zrobiłeś, ale w istocie:
where
jest tylko konstruktem składniowym (nie cukrem ), który jest przydatny tylko przy definiowaniu funkcji .let ... in
jest wyrażeniem samym w sobie , więc możesz ich używać wszędzie tam, gdzie możesz umieścić wyrażenie. Jako samo wyrażenie nie może być używane do wiązania rzeczy dla strażników.Na koniec możesz także używać
let
w składaniu list:źródło