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.
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.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.Respuestas:
1: El problema del ejemplo
es el parámetro
x
. Las cosas en lawhere
cláusula pueden referirse solo a los parámetros de la funciónf
(no hay ninguna) y las cosas en ámbitos externos.2: Para usar a
where
en el primer ejemplo, puede introducir una segunda función nombrada que tomax
como parámetro, así:o así:
3: Aquí hay un ejemplo completo sin los
...
's:4: Cuándo usar
let
owhere
es cuestión de gustos. Utilizolet
para enfatizar un cálculo (moviéndolo hacia el frente) ywhere
para enfatizar el flujo del programa (moviendo el cálculo hacia atrás).fuente
Si bien existe la diferencia técnica con respecto a los guardias que señaló ephemient, también hay una diferencia conceptual en si desea poner la fórmula principal al principio con variables adicionales definidas a continuación (
where
) o si desea definir todo por adelantado y poner la fórmula debajo (let
). Cada estilo tiene un énfasis diferente y se ven ambos usados en trabajos de matemáticas, libros de texto, etc. Generalmente, las variables que son lo suficientemente poco intuitivas como para que la fórmula no tenga sentido sin ellas deben definirse arriba; las variables que son intuitivas debido al contexto o sus nombres deben definirse a continuación. Por ejemplo, en el ejemplo de hasVowel de ephemient, el significado devowels
es obvio y, por lo tanto, no es necesario definirlo por encima de su uso (sin tener en cuenta el hecho de quelet
no funcionaría debido a la guardia).fuente
Legal:
Ilegal:
Legal:
No legal: (a diferencia de ML)
fuente
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
es nueva línea)Encontré este ejemplo de LYHFGG útil:
let
es una expresión para que pueda poner unlet
lugar (!) donde pueden ir las expresiones.En otras palabras, en el ejemplo anterior es no posible utilizar
where
simplemente para reemplazarlet
(sin tal vez usando un poco más detalladocase
expresión combinada conwhere
).fuente
Lamentablemente, la mayoría de las respuestas aquí son demasiado técnicas para un principiante.
LHYFGG tiene un capítulo relevante al respecto, que debe leer si aún no lo ha hecho, pero en esencia:
where
es solo una construcción sintáctica (no un azúcar ) que son útiles solo en las definiciones de funciones .let ... in
es una expresión en sí misma , por lo que puede usarlos siempre que pueda poner una expresión. Siendo una expresión en sí misma, no puede usarse para atar cosas para los guardias.Por último, también puede usar
let
en listas por comprensión:fuente