Soy nuevo en Haskell y estoy muy confundido con Where vs. Let . Ambos parecen tener un propósito similar. He leído algunas comparaciones entre Dónde y Dejar, pero tengo problemas para discernir cuándo usar cada una. ¿Podría alguien proporcionar algún contexto o quizás algunos ejemplos que demuestren cuándo usar uno sobre el otro?
Donde vs Dejar
Una
where
cláusula solo se puede definir a nivel de definición de función. Por lo general, eso es idéntico al alcance de lalet
definición. La única diferencia es cuando se utilizan protectores . El alcance de lawhere
cláusula se extiende a todos los guardias. Por el contrario, el alcance de unalet
expresión es solo la cláusula de función actual y la protección, si corresponde.
La Wiki de Haskell es muy detallada y proporciona varios casos, pero utiliza ejemplos hipotéticos. Encuentro sus explicaciones demasiado breves para un principiante.
Ventajas de Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
no funcionará, porque where se refiere al patrón que coincide con f =, donde no hay x en el alcance. Por el contrario, si hubiera comenzado con let, no tendría problemas.
Wiki de Haskell sobre las ventajas de Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Ventajas de Dónde :
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)
Declaración frente a expresión
La wiki de Haskell menciona que la cláusula Where es declarativa mientras que la expresión Let es expresiva. Aparte del estilo, ¿cómo funcionan de manera diferente?
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 ...
- En el primer ejemplo, ¿por qué está el alcance Let in pero dónde no?
- ¿Es posible aplicar Where al primer ejemplo?
- ¿Pueden algunos aplicar esto a ejemplos reales donde las variables representan expresiones reales?
- ¿Existe una regla general a seguir cuando usar cada uno?
Actualizar
Para aquellos que vienen por este hilo más adelante, encontré la mejor explicación que se puede encontrar aquí: " Una suave introducción a Haskell ".
Dejemos Expressions.
Las expresiones let de Haskell son útiles siempre que se requiera un conjunto anidado de enlaces. Como ejemplo simple, considere:
let y = a*b f x = (x+y)/y in f c + f d
El conjunto de enlaces creados por una expresión let es recursivo entre sí, y los enlaces de patrones se tratan como patrones perezosos (es decir, llevan un ~ implícito). El único tipo de declaraciones permitidas son las firmas de tipos, los enlaces de funciones y los enlaces de patrones.
Dónde Cláusulas.
A veces es conveniente establecer el alcance de los enlaces sobre varias ecuaciones protegidas, lo que requiere una cláusula where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Tenga en cuenta que esto no se puede hacer con una expresión let, que solo se aplica a la expresión que encierra. Una cláusula where solo se permite en el nivel superior de un conjunto de ecuaciones o expresión de caso. Las mismas propiedades y restricciones sobre los enlaces en las expresiones let se aplican a las de las cláusulas where. Estas dos formas de ámbito anidado parecen muy similares, pero recuerde que una expresión let es una expresión, mientras que una cláusula where no lo es; es parte de la sintaxis de las declaraciones de funciones y las expresiones de casos.
f = body where x = xbody; y = ybody ...
significaf = let x = xbody; y = ybody ... in body
case .... of ... where
expresión de alguna manera? No estoy seguro de esto.
let
ywhere
cuando empecé a aprender Haskell. Creo que la mejor manera de entenderlo es darse cuenta de que hay muy poca diferencia entre los dos y, por lo tanto, no hay nada de qué preocuparse. El significado dewhere
dado en términos de alet
través de una transformación mecánica muy simple. Ver haskell.org/onlinereport/decls.html#sect4.4.3.2 Esta transformación existe solo por conveniencia de notación, en realidad.