Sono nuovo di Haskell e sono molto confuso da Where vs. Let . Entrambi sembrano fornire uno scopo simile. Ho letto alcuni confronti tra Where vs. Let, ma ho difficoltà a discernere quando usarli. Qualcuno potrebbe fornire un contesto o forse alcuni esempi che dimostrano quando utilizzare l'uno sull'altro?
Where vs. Let
Una
where
clausola può essere definita solo a livello di definizione di una funzione. Di solito, questo è identico all'ambito dellalet
definizione. L'unica differenza è quando vengono utilizzate le guardie . L'ambito dellawhere
clausola si estende a tutte le guardie. Al contrario, l'ambito dilet
un'espressione è solo la clausola di funzione corrente e la guardia, se presente.
Il Wiki di Haskell è molto dettagliato e fornisce vari casi ma utilizza esempi ipotetici. Trovo le sue spiegazioni troppo brevi per un principiante.
Vantaggi di Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
non funzionerà, perché where si riferisce al pattern matching f =, dove nessuna x è nell'ambito. Al contrario, se avessi iniziato con let, non avresti avuto problemi.
Haskell Wiki sui vantaggi di Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Vantaggi di Where :
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)
Dichiarazione contro espressione
Il wiki di Haskell afferma che la clausola Where è dichiarativa mentre l' espressione Let è espressiva. A parte lo stile, come si comportano diversamente?
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 ...
- Nel primo esempio, perché l' ambito Let in è ma Where no?
- È possibile applicare Where al primo esempio?
- Alcuni possono applicare questo ad esempi reali in cui le variabili rappresentano espressioni reali?
- Esiste una regola pratica generale da seguire quando utilizzarli?
Aggiornare
Per coloro che vengono da questo thread più avanti ho trovato la migliore spiegazione da trovare qui: " A Gentle Introduction to Haskell ".
Lasciate che le espressioni.
Le espressioni let di Haskell sono utili ogni volta che è richiesto un insieme nidificato di associazioni. Come semplice esempio, considera:
let y = a*b f x = (x+y)/y in f c + f d
L'insieme di associazioni create da un'espressione let è reciprocamente ricorsiva e le associazioni di pattern sono trattate come pattern pigri (cioè portano un ~ implicito). L'unico tipo di dichiarazioni consentite sono le firme dei tipi, le associazioni di funzioni e le associazioni di modelli.
Dove clausole.
A volte è conveniente definire l'ambito delle associazioni su diverse equazioni protette, che richiedono una clausola where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Notare che ciò non può essere fatto con un'espressione let, che si limita a limitarsi all'espressione che racchiude. Una clausola where è consentita solo al livello più alto di un insieme di equazioni o espressioni di casi. Le stesse proprietà e gli stessi vincoli sui collegamenti nelle espressioni let si applicano a quelli nelle clausole where. Queste due forme di ambito annidato sembrano molto simili, ma ricorda che un'espressione let è un'espressione, mentre una clausola where non lo è: fa parte della sintassi delle dichiarazioni di funzione e delle espressioni case.
f = body where x = xbody; y = ybody ...
significaf = let x = xbody; y = ybody ... in body
case .... of ... where
qualche modo un'espressione let in un'espressione? Non sono sicuro di questo.
let
ewhere
quando ho iniziato a imparare Haskell. Penso che il modo migliore per capirlo sia rendersi conto che c'è pochissima differenza tra i due, e quindi niente di cui preoccuparsi. Il significato diwhere
dato in termini dilet
attraverso una trasformazione meccanica molto semplice. Vedi haskell.org/onlinereport/decls.html#sect4.4.3.2 Questa trasformazione esiste solo per comodità di notazione, in realtà.