Haskell: Onde vs. Let

Eu sou novo em Haskell e estou muito confuso comOnde vs.Deixei. Ambos parecem fornecer um propósito semelhante. Eu li algumas comparações entreOnde vs.Deixei mas estou tendo problemas para discernir quando usar cada um. Alguém poderia fornecer algum contexto ou talvez alguns exemplos que demonstrem quando usar um sobre o outro?

Where vs. Let

A where A cláusula pode ser definida apenas no nível de uma definição de função. Geralmente, isso é idêntico ao escopo delet definição.A única diferença é quando guardas estão sendo usados. O escopo dawhere A cláusula se estende a todos os guardas. Por outro lado, o escopo de umlet expressão é apenas a cláusula de função atual e guarda, se houver.

Folha de dicas de Haskell

oHaskell Wiki é muito detalhado e fornece vários casos, mas usa exemplos hipotéticos. Acho as explicações muito curtas para um iniciante.

Vantagens de Let:

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

Control.Monad.State

não funcionará, porque where se refere ao padrão correspondente f =, onde nenhum x está no escopo. Por outro lado, se você tivesse iniciado com let, não teria problemas.

Wiki Haskell sobre Vantagens de Let

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

Vantagens de onde:

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)

Declaração vs. Expressão

O wiki de Haskell menciona que oOnde cláusula é declarativa enquanto oDeixei expressão é expressiva. Além do estilo, como eles funcionam de maneira 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 ...
No primeiro exemplo, por que oDeixei no escopo, masOnde não é?É possível aplicarOnde para o primeiro exemplo?Alguns podem aplicar isso a exemplos reais em que as variáveis representam expressões reais?Existe uma regra geral a seguir quando usar cada um?Atualizar

Para aqueles que aparecerem mais tarde neste tópico, encontrei a melhor explicação a ser encontrada aqui: "Uma introdução suave a Haskell"

Deixe expressões.

As expressões let de Haskell são úteis sempre que um conjunto aninhado de ligações é necessário. Como um exemplo simples, considere:

let y   = a*b
    f x = (x+y)/y
in f c + f d

O conjunto de ligações criado por uma expressão let é mutuamente recursivo e as ligações de padrões são tratadas como padrões preguiçosos (ou seja, eles carregam um implícito). O único tipo de declaração permitido é assinaturas de tipo, ligações de função e ligações de padrão.

Cláusulas Where.

Às vezes, é conveniente escopo ligações de várias equações protegidas, o que requer uma cláusula where:

f x y  |  y>z           =  ...
       |  y==z          =  ...
       |  y<z           =  ...
     where z = x*x

Observe que isso não pode ser feito com uma expressão let, que apenas escopo sobre a expressão que ela inclui. Uma cláusula where é permitida apenas no nível superior de um conjunto de equações ou expressão de caso. As mesmas propriedades e restrições nas ligações em expressões permitem aplicar às cláusulas where. Essas duas formas de escopo aninhado parecem muito semelhantes, mas lembre-se de que uma expressão let é uma expressão, enquanto uma cláusula where não é - faz parte da sintaxe das declarações de função e expressões de caso.

questionAnswers(4)

yourAnswerToTheQuestion