Je suis nouveau à Haskell et je suis très confus par Where vs. Let . Ils semblent tous deux avoir un objectif similaire. J'ai lu quelques comparaisons entre Where vs. Let mais j'ai du mal à discerner quand les utiliser. Quelqu'un pourrait-il fournir un contexte ou peut-être quelques exemples qui montrent quand utiliser l'un plutôt que l'autre?
Où vs laisser
Une
where
clause ne peut être définie qu'au niveau d'une définition de fonction. Habituellement, cela correspond à la portée de lalet
définition. La seule différence est lorsque des gardes sont utilisés . La portée de lawhere
clause s'étend à tous les gardiens. En revanche, la portée d'unelet
expression est uniquement la clause de fonction actuelle et la garde, le cas échéant.
Le Wiki Haskell est très détaillé et fournit divers cas mais il utilise des exemples hypothétiques. Je trouve ses explications trop brèves pour un débutant.
Avantages de Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
ne fonctionnera pas, car where se réfère au modèle correspondant à f =, où aucun x n'est dans la portée. En revanche, si vous aviez commencé avec let, vous n'auriez aucun problème.
Haskell Wiki sur les avantages de Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Avantages de Où :
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)
Le wiki Haskell mentionne que la clause Where est déclarative tandis que l' expression Let est expressive. Mis à part le style, comment fonctionnent-ils différemment?
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 ...
- Dans le premier exemple, pourquoi le Let est-il dans la portée mais Où ne l'est pas?
- Est-il possible d'appliquer Où au premier exemple?
- Certains peuvent-ils appliquer cela à des exemples réels où les variables représentent des expressions réelles?
- Existe-t-il une règle générale à suivre pour utiliser chacun d'eux?
Mettre à jour
Pour ceux qui reviennent plus tard sur ce fil, j'ai trouvé la meilleure explication ici: " Une introduction douce à Haskell ".
Laissez Expressions.
Les expressions let de Haskell sont utiles chaque fois qu'un ensemble imbriqué de liaisons est requis. À titre d'exemple simple, considérons:
let y = a*b f x = (x+y)/y in f c + f d
L'ensemble des liaisons créées par une expression let est mutuellement récursive et les liaisons de motifs sont traitées comme des motifs paresseux (c'est-à-dire qu'elles portent un ~ implicite). Les seuls types de déclarations autorisés sont les signatures de type, les liaisons de fonction et les liaisons de modèle.
Où les clauses.
Parfois, il est pratique de définir des liaisons sur plusieurs équations protégées, ce qui nécessite une clause where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Notez que cela ne peut pas être fait avec une expression let, qui ne s'étend que sur l'expression qu'elle englobe. Une clause where n'est autorisée qu'au niveau supérieur d'un ensemble d'équations ou d'une expression de cas. Les mêmes propriétés et contraintes sur les liaisons dans les expressions let s'appliquent à celles des clauses where. Ces deux formes de portée imbriquée semblent très similaires, mais rappelez-vous qu'une expression let est une expression, alors qu'une clause where ne l'est pas - elle fait partie de la syntaxe des déclarations de fonction et des expressions case.
let
etwhere
quand j'ai commencé à apprendre Haskell. Je pense que la meilleure façon de le comprendre est de se rendre compte qu'il y a très peu de différence entre les deux, et donc rien à craindre. Le sens duwhere
donné en termes delet
par une transformation mécanique très simple. Voir haskell.org/onlinereport/decls.html#sect4.4.3.2 Cette transformation existe uniquement à des fins de notation, en réalité.f = body where x = xbody; y = ybody ...
signifief = let x = xbody; y = ybody ... in body
case .... of ... where
expression d' une manière ou d' une autre? Je ne suis pas certain de cela.Réponses:
1: Le problème dans l'exemple
est le paramètre
x
. Les éléments de lawhere
clause ne peuvent faire référence qu'aux paramètres de la fonctionf
(il n'y en a pas) et aux éléments des portées externes.2: Pour utiliser a
where
dans le premier exemple, vous pouvez introduire une deuxième fonction nommée qui prend lex
comme paramètre, comme ceci:ou comme ça:
3: Voici un exemple complet sans les
...
's:4: Quand utiliser
let
ouwhere
c'est une question de goût. J'utiliselet
pour accentuer un calcul (en le déplaçant vers l'avant) etwhere
pour souligner le déroulement du programme (en déplaçant le calcul vers l'arrière).la source
Bien qu'il y ait la différence technique par rapport aux gardes que l'éphémère a souligné, il existe également une différence conceptuelle dans le fait de savoir si vous voulez mettre la formule principale au début avec des variables supplémentaires définies ci-dessous (
where
) ou si vous voulez tout définir à l'avance et mettre la formule ci-dessous (let
). Chaque style a une emphase différente et vous voyez les deux utilisés dans les articles de mathématiques, les manuels, etc. En général, les variables qui sont suffisamment peu intuitives pour que la formule n'ait pas de sens sans elles doivent être définies ci-dessus; les variables intuitives en raison du contexte ou de leurs noms doivent être définies ci-dessous. Par exemple, dans l'exemple hasVowel d'Ephemient, la signification devowels
est évidente et il n'est donc pas nécessaire de la définir au-dessus de son utilisation (sans tenir compte du fait quelet
cela ne fonctionnerait pas à cause de la garde).la source
Légal:
Non légal:
Légal:
Non légal: (contrairement à ML)
la source
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
est une nouvelle ligne)J'ai trouvé cet exemple de LYHFGG utile:
let
est une expression afin que vous puissiez mettre unlet
n'importe où (!) où les expressions peuvent aller.En d'autres termes, dans l'exemple ci-dessus, il n'est pas possible d'utiliser
where
pour simplement remplacerlet
(sans peut-être utiliser unecase
expression plus verbeuse combinée avecwhere
).la source
Malheureusement, la plupart des réponses ici sont trop techniques pour un débutant.
LHYFGG a un chapitre pertinent à ce sujet - que vous devriez lire si vous ne l'avez pas déjà fait, mais en substance:
where
est juste une construction syntaxique (pas un sucre ) qui n'est utile que pour les définitions de fonction .let ... in
est une expression elle - même , vous pouvez donc les utiliser partout où vous pouvez mettre une expression. Étant une expression en soi, il ne peut pas être utilisé pour lier des choses pour les gardes.Enfin, vous pouvez également utiliser
let
dans les compréhensions de liste:la source