Ich bin neu in Haskell und ich bin sehr verwirrt von Where vs. Let . Sie scheinen beide einen ähnlichen Zweck zu erfüllen. Ich habe einige Vergleiche zwischen Where vs. Let gelesen, aber ich habe Probleme zu erkennen, wann ich sie verwenden soll. Könnte jemand bitte einen Kontext oder vielleicht ein paar Beispiele angeben, die zeigen, wann man sie übereinander verwendet?
Wo gegen lassen
Eine
where
Klausel kann nur auf der Ebene einer Funktionsdefinition definiert werden. Normalerweise ist das identisch mit demlet
Definitionsumfang. Der einzige Unterschied besteht darin, wann Wachen verwendet werden . Der Geltungsbereich derwhere
Klausel erstreckt sich über alle Wachen. Im Gegensatz dazu ist der Umfang eineslet
Ausdrucks nur die aktuelle Funktionsklausel und ggf. der Schutz.
Das Haskell-Wiki ist sehr detailliert und bietet verschiedene Fälle, verwendet jedoch hypothetische Beispiele. Ich finde die Erklärungen für einen Anfänger zu kurz.
Vorteile von Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
funktioniert nicht, da sich where auf die Musterübereinstimmung f = bezieht, wobei kein x im Gültigkeitsbereich liegt. Wenn Sie dagegen mit let begonnen hätten, hätten Sie keine Probleme.
Haskell Wiki über die Vorteile von Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Vorteile von Wo :
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)
Das Haskell-Wiki erwähnt, dass die Where- Klausel deklarativ ist, während der Let- Ausdruck expressiv ist. Wie verhalten sie sich neben dem Stil anders?
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 ...
- Im ersten Beispiel, warum ist der Bereich Einlassen, aber wo nicht?
- Ist es möglich, Wo auf das erste Beispiel anzuwenden ?
- Können einige dies auf reale Beispiele anwenden, bei denen die Variablen tatsächliche Ausdrücke darstellen?
- Gibt es eine allgemeine Faustregel, die zu befolgen ist, wann sie verwendet werden sollen?
Aktualisieren
Für diejenigen, die später von diesem Thread kommen, fand ich die beste Erklärung hier: " Eine sanfte Einführung in Haskell ".
Lassen Sie Ausdrücke.
Haskells let-Ausdrücke sind immer dann nützlich, wenn ein verschachtelter Satz von Bindungen erforderlich ist. Betrachten Sie als einfaches Beispiel:
let y = a*b f x = (x+y)/y in f c + f d
Der Satz von Bindungen, der durch einen let-Ausdruck erzeugt wird, ist gegenseitig rekursiv, und Musterbindungen werden als faule Muster behandelt (dh sie tragen ein implizites ~). Die einzigen zulässigen Deklarationen sind Typensignaturen, Funktionsbindungen und Musterbindungen.
Where-Klauseln.
Manchmal ist es zweckmäßig, Bindungen über mehrere geschützte Gleichungen hinweg zu erfassen, was eine where-Klausel erfordert:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Beachten Sie, dass dies nicht mit einem let-Ausdruck möglich ist, der nur den darin enthaltenen Ausdruck abdeckt. Eine where-Klausel ist nur auf der obersten Ebene eines Satzes von Gleichungen oder eines Fallausdrucks zulässig. Die gleichen Eigenschaften und Einschränkungen für Bindungen in let-Ausdrücken gelten für diejenigen in where-Klauseln. Diese beiden Formen des verschachtelten Bereichs scheinen sehr ähnlich zu sein, aber denken Sie daran, dass ein let-Ausdruck ein Ausdruck ist, während eine where-Klausel dies nicht ist - er ist Teil der Syntax von Funktionsdeklarationen und case-Ausdrücken.
f = body where x = xbody; y = ybody ...
bedeutetf = let x = xbody; y = ybody ... in body
case .... of ... where
Ausdruck irgendwie in einen Ausdruck umzuwandeln ? Da bin ich mir nicht sicher.
let
undwhere
als ich anfing, Haskell zu lernen. Ich denke, der beste Weg, dies zu verstehen, besteht darin, zu erkennen, dass es kaum einen Unterschied zwischen den beiden gibt und daher kein Grund zur Sorge besteht. Die Bedeutung vonwhere
gegebenlet
durch eine sehr einfache mechanische Transformation gegeben. Siehe haskell.org/onlinereport/decls.html#sect4.4.3.2. Diese Transformation dient eigentlich nur zur Vereinfachung der Notation.