Haskell: Dónde vs. Let

Soy nuevo en Haskell y estoy muy confundido porDónde vs.Dejar. Ambos parecen proporcionar un propósito similar. He leído algunas comparaciones entreDónde vs.Dejar pero tengo problemas para discernir cuándo usar cada uno. ¿Podría alguien proporcionar algún contexto o quizás algunos ejemplos que demuestren cuándo usar uno sobre el otro?

Donde vs. Let

A where La cláusula solo se puede definir a nivel de una definición de función. Por lo general, eso es idéntico al alcance delet definición.La única diferencia es cuando se usan guardias. El alcance de lawhere La cláusula se extiende sobre todos los guardias. En contraste, el alcance de unlet expresión es solo la cláusula de función actual y guardia, si hay alguna.

Haskell Cheat Sheet

losWiki Haskell Es muy detallado y proporciona varios casos, pero utiliza ejemplos hipotéticos. Sus explicaciones me parecen demasiado breves para un principiante.

Ventajas de Let:

f :: State s a
f = State $ \x -> y
   where y = ... x ...

Control.Monad.State

no funcionará, porque donde se refiere al patrón que coincide con f =, donde no x está dentro del alcance. Por el contrario, si hubiera comenzado con let, no tendría problemas.

Haskell Wiki sobre Ventajas de Let

f :: State s a
f = State $ \x ->
   let y = ... x ...
   in  y

Ventajas de donde:

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 vs. Expresión

El wiki de Haskell menciona que elDónde cláusula es declarativa mientras que laDejar La expresión es expresiva. Además 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é es elDejar en alcance peroDónde ¿no es?¿Es posible aplicar?Dónde al primer ejemplo?¿Pueden algunos aplicar esto a ejemplos reales donde las variables representan expresiones reales?¿Hay una regla general a seguir cuando usar cada uno?Actualizar

Para aquellos que vienen con este hilo más adelante, encontré la mejor explicación aquí: "Una suave introducción a Haskell".

Deje expresiones.

Las expresiones let de Haskell son útiles siempre que se requiera un conjunto anidado de enlaces. Como un simple ejemplo, 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 mutuamente recursivo, y los enlaces de patrones se tratan como patrones perezosos (es decir, llevan un ~ implícito). El único tipo de declaraciones permitidas son firmas de tipo, enlaces de función y enlaces de patrón.

Donde las cláusulas.

A veces es conveniente establecer enlaces de alcance 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 extiende sobre la expresión que encierra. Una cláusula where solo está permitida en el nivel superior de un conjunto de ecuaciones o expresiones de casos. Las mismas propiedades y restricciones en los enlaces en expresiones let se aplican a las cláusulas where. Estas dos formas de alcance 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 expresiones de casos.

Respuestas a la pregunta(4)

Su respuesta a la pregunta