Je suis nouveau en Haskell et je suis très confus par Où vs. Let. Ils semblent tous les deux avoir un but similaire. J'ai lu quelques comparaisons entre Où vs. Let mais j'ai du mal à discerner quand utiliser chacun. Est-ce que quelqu'un pourrait fournir un peu de contexte ou peut-être quelques exemples pour montrer quand utiliser l'un plutôt que l'autre?
Où vs. Let
Une clause
where
ne peut être définie qu'au niveau de la définition d'une fonction. Habituellement, cela correspond à la portée de la définitionlet
. La seule différence est lorsqu'on utilise des gardes. La portée de la clausewhere
s'étend à travers toutes les gardes. En revanche, la portée d'une expressionlet
est uniquement la clause de fonction actuelle et la garde, le cas échéant.
Le Wiki Haskell est très détaillé et fournit différents cas mais il utilise des exemples hypothétiques. Je trouve ses explications trop succinctes pour un débutant.
Avantages du Let:
f :: State s a
f = State $ \x -> y
where y = ... x ...
ne fonctionnera pas, car where se réfère à la correspondance des motifs f =, où aucun x n'est en portée. En revanche, si vous aviez commencé avec let, alors vous n'auriez pas eu de problème.
Wiki Haskell sur les avantages du Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Avantages du 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)
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?
Style de déclaration | Style d'expression
--------------------------------------+---------------------------------------------
clause where | expression let
arguments LHS: f x = x*x | Abstraction lambda: f = \x -> x*x
Correspondance des motifs: f [] = 0 | expression case: f xs = case xs de [] -> 0
Gardes: f [x] | x>0 = 'a' | expression if: f [x] = si x>0 alors 'a' else ...
- Dans le premier exemple, pourquoi le Let est-il dans la portée mais pas le Où?
- Est-il possible d'appliquer Où au premier exemple?
- Est-ce que quelqu'un peut appliquer cela à des exemples réels où les variables représentent des expressions réelles?
- Y a-t-il une règle générale à suivre pour savoir quand utiliser chacun?
Mise à jour
Pour ceux qui consultent ce fil plus tard, j'ai trouvé la meilleure explication ici: "Une introduction douce à Haskell".
Expressions Let.
Les expressions let de Haskell sont utiles chaque fois qu'un ensemble imbriqué de liaisons est nécessaire. À titre d'exemple simple, considérez:
let y = a*b f x = (x+y)/y in f c + f d
L'ensemble de liaisons créé par une expression let est mutuellement récursif, et les liaisons de motifs sont traitées comme des motifs paresseux (c'est-à-dire qu'elles portent un implicite ~). Le seul type de déclarations autorisé est les signatures de type, les liaisons de fonction, et les liaisons de motifs.
Clauses Where.
Parfois, il est pratique de définir une portée de liaisons sur plusieurs équations gardées, ce qui nécessite une clause where:
f x y | y>z = ... | y==z = ... | y
`
Remarquez que cela ne peut pas être fait avec une expression let, qui ne s'applique qu'à 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 case. Les mêmes propriétés et contraintes sur les liaisons dans les expressions let s'appliquent à celles dans les clauses where. Ces deux formes de portée imbriquée semblent très similaires, mais rappelez-vous qu'une expression let est une expression, tandis qu'une clause where ne l'est pas -- elle fait partie de la syntaxe des déclarations de fonction et des expressions de cas.
`
10 votes
J'étais perplexe par la différence entre
let
etwhere
lorsque j'ai commencé à apprendre Haskell. Je pense que la meilleure façon de le comprendre est de réaliser qu'il y a très peu de différence entre les deux, et donc rien à craindre. Le sens dewhere
est donné en termes delet
à travers une transformation mécanique très simple. Voir haskell.org/onlinereport/decls.html#sect4.4.3.2 Cette transformation existe uniquement pour des raisons de commodité notationale, en réalité.0 votes
Je vais généralement utiliser l'un ou l'autre en fonction de ce que je veux définir en premier. Par exemple, les gens utilisent souvent les fonctions, puis les définissent là où ils veulent. Let est utilisé si on veut une sorte de fonction à l'aspect impératif.
0 votes
@Tom Ellis, Tom, j'essayais de comprendre le lien auquel vous faites référence, mais c'était trop difficile pour moi. Pourriez-vous expliquer cette simple transformation aux simples mortels?
1 votes
@jhegedus :
f = corps où x = corps de x; y = corps de y ...
signifief = laisser x = corps de x; y = corps de y ... dans le corps
0 votes
Merci Tom ! Est-il possible d'inverser la situation ? Est-il possible de transformer une expression let en une expression
case .... of ... where
d'une manière ou d'une autre ? Je ne suis pas sûr de cela.