Хаскелл: где против пусть



Я новичок в Haskell, и я очень смущен здесь и пусть. Они оба, кажется, обеспечивают аналогичную цель. Я прочитал несколько сравнений между здесь и пусть но у меня возникли проблемы лишь когда использовать каждый. Может ли кто-нибудь предоставить некоторый контекст или, возможно, несколько примеров, которые демонстрируют, когда использовать один над другим?




где и пусть



A where предложение может быть определено только на уровне определения функции. Обычно это совпадает с областью let определение. единственная разница, когда охранники используются. Сфера применения where пункт распространяется на всех охранников. В отличие от рамки let выражение-это только текущее предложение функции и guard, если таковые имеются.




Шпаргалка Хаскелла



The Haskell Wiki очень подробно и предоставляет различные случаи, но использует гипотетические примеры. Я нахожу его объяснения слишком краткими для новичка.



преимущества Let:



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


управление.Монада.Государство




не будет работать, потому что куда относится
соответствие шаблону f =, где нет x
находится в поле зрения. Напротив, если бы вы имели
начал с let, а потом не стал бы
иметь тревогу.




Haskell Wiki on Преимущества Let



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


преимущества 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)


объявление против выражения



Haskell wiki упоминает, что здесь предложение является декларативным, в то время как пусть выражение выразительным. Помимо стиля, как они работают по-разному?



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 ...



  1. в первом примере, почему это пусть в рамках но здесь нет?

  2. можно ли применять здесь в первом примере?

  3. могут ли некоторые применить это к реальным примерам, где переменные представляют фактические выражения?

  4. есть ли общее эмпирическое правило, чтобы следовать, когда использовать каждый?




обновление



для тех, кто приходит по этой теме позже, я нашел лучшее объяснение, которое можно найти здесь:"введение в Хаскелл".




Давайте Выражений.



выражения Haskell let полезны
всякий раз, когда вложенный набор Привязок
требуемый. В качестве простого примера,
рассмотрим:



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


набор Привязок, созданных let
выражение является взаимно рекурсивным, и
привязки шаблонов рассматриваются как ленивые
шаблоны (т. е. они несут неявный
~). Единственный вид деклараций
разрешены сигнатуры типов,
привязки функций, и узор
фурнитура.



Предложения Where.



иногда удобно к объему
привязки над несколькими охраняемыми
уравнения, для которых требуется где
статья:



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


обратите внимание, что это не может быть сделано с выражением let, которое охватывает только выражение, которое оно заключает. Предложение where допускается только на верхнем уровне набора уравнений или выражения case. Те же свойства и ограничения на привязки в выражениях let применяются к тем, в которых пункты. Эти две формы вложенной области кажутся очень похожими, но помните, что выражение let является выражением, тогда как предложение where не является -- это часть синтаксиса объявлений функций и выражений case.


580   4  

4 ответов:

1: Проблема в Примеру

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

параметр x. Вещи в where предложение может ссылаться только на параметры функции f (их нет)и вещи во внешних областях.

2: использовать where в первом примере можно ввести вторую именованную функцию это занимает x в качестве параметра, как это:

f = State f'
f' x = y
    where y = ... x ...

или такой:

f = State f'
    where
    f' x = y
        where y = ... x ...

3: Вот полный пример без ... ' s:

module StateExample where

data State a s = State (s -> (a, s))

f1 :: State Int (Int, Int)
f1 = State $ \state@(a, b) ->
    let
        hypot = a^2 + b^2
        result = (hypot, state)
    in result

f2 :: State Int (Int, Int)
f2 = State f
    where
    f state@(a, b) = result
        where
        hypot = a^2 + b^2
        result = (hypot, state)

4: Когда использовать let или where - это дело вкуса. Я использую let чтобы подчеркнуть вычисление (перемещая его на фронт) и where чтобы подчеркнуть поток программы (перемещая вычисление назад).

хотя есть техническая разница в отношении охранников, на которые указал Эфемер, есть также концептуальная разница в том, хотите ли вы поместить основную формулу вперед с дополнительными переменными, определенными ниже (where) или если вы хотите, чтобы определить все заранее и поставить формулу ниже (let). Каждый стиль имеет различный акцент, и вы видите, как используется в математических работах, учебниках и т. д. Как правило, переменные, которые достаточно неинтуитивны, что формула не делает смысл без них должен быть определен выше; переменные, которые интуитивно понятны из-за контекста или их имена должны быть определены ниже. Например, в Примере эфемерного hasVowel значение vowels очевидно, и поэтому его не нужно определять выше его использования (не обращая внимания на то, что let не будет работать из-за предохранителя).

Legal:

main = print (1 + (let i = 10 in 2 * i + 1))

не законно:

main = print (1 + (2 * i + 1 where i = 10))

Legal:

hasVowel [] = False
hasVowel (x:xs)
  | x `elem` vowels = True
  | otherwise = False
  where vowels = "AEIOUaeiou"

не законно: (в отличие от ML)

let vowels = "AEIOUaeiou"
in hasVowel = ...

Я нашел этот пример от LYHFGG полезная:

ghci> 4 * (let a = 9 in a + 1) + 2  
42  

let это выражение, так что вы можете поставить letвезде(!) где выражения могут пойти.

другими словами, в приведенном выше примере это не можно использовать where просто заменить let (возможно, не используя некоторые более подробные case выражения в сочетании с where).

Comments

    Ничего не найдено.