Я новичок в Haskell, и меня очень смущает Where vs. Let . У них обоих, похоже, схожая цель. Я прочитал несколько сравнений между Where и Let, но мне трудно понять, когда использовать каждый. Может ли кто-нибудь предоставить некоторый контекст или, возможно, несколько примеров, демонстрирующих, когда использовать одно вместо другого?
Где vs. пусть
Предложение
where
может быть определено только на уровне определения функции. Обычно это совпадает с объемомlet
определения. Единственная разница в том, когда используются охранники . Сфера действияwhere
статьи распространяется на всех охранников. Напротив, объемlet
выражения - это только текущее предложение функции и защита, если таковая имеется.
Haskell Wiki очень подробно и предоставляет различные случаи , но он использует гипотетические примеры. Я нахожу его объяснения слишком краткими для новичка.
Преимущества Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
не будет работать, потому что где относится к сопоставлению с образцом f =, где x не входит в область видимости. Напротив, если бы вы начали с let, у вас не было бы проблем.
Haskell Wiki о преимуществах Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Преимущества места :
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 упоминается, что предложение Where является декларативным, а выражение Let - выразительным. Помимо стиля, чем они отличаются?
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 ...
- В первом примере почему Let в области видимости, а где нет?
- Можно ли применить Where к первому примеру?
- Можно ли применить это к реальным примерам, где переменные представляют собой фактические выражения?
- Есть ли какое-то общее практическое правило, когда использовать каждый из них?
Обновить
Для тех, кто позже зайдет в эту ветку, я нашел лучшее объяснение здесь: « Нежное введение в Haskell ».
Позвольте выражениям.
Выражения let в Haskell полезны всякий раз, когда требуется вложенный набор привязок. В качестве простого примера рассмотрим:
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 применяются к тем, что в предложениях where. Эти две формы вложенной области видимости кажутся очень похожими, но помните, что выражение let - это выражение, а предложение where - нет - это часть синтаксиса объявлений функций и выражений case.
let
и ,where
когда я впервые начал изучать Haskell. Я думаю, что лучший способ понять это - понять, что между ними очень мало различий, и поэтому не о чем беспокоиться. Значениеwhere
дано в терминахlet
очень простого механического преобразования. См. Haskell.org/onlinereport/decls.html#sect4.4.3.2 На самом деле это преобразование существует только для удобства записи.f = body where x = xbody; y = ybody ...
означаетf = let x = xbody; y = ybody ... in body
case .... of ... where
выражение? Я не уверен в этом.Ответы:
1: Проблема в примере
это параметр
x
. Вещи вwhere
предложении могут относиться только к параметрам функцииf
(их нет) и вещам во внешних областях.2: Чтобы использовать
where
в первом примере, вы можете ввести вторую именованную функцию, которая принимает вx
качестве параметра, например:или вот так:
3: Вот полный пример без
...
символов:4: Когда использовать
let
илиwhere
это дело вкуса. Я использую,let
чтобы выделить вычисления (перемещая их на передний план) иwhere
подчеркивая поток программы (перемещая вычисления на задний план).источник
Хотя существует техническая разница в отношении охранников, на которые указал эфемиент, существует также концептуальная разница в том, хотите ли вы поставить основную формулу заранее с дополнительными переменными, определенными ниже (
where
), или хотите ли вы заранее определить все и поставить формулу ниже (let
). У каждого стиля свой акцент, и вы видите, что оба они используются в математических работах, учебниках и т. Д. Как правило, переменные, которые достаточно неинтуитивны, чтобы формула не имела смысла без них, должны быть определены выше; переменные, которые интуитивно понятны из-за контекста или их имен, должны быть определены ниже. Например, в примере hasVowel от ephemient значение словаvowels
очевидно, поэтому его не нужно определять выше, чем его использование (без учета того факта, чтоlet
это не сработает из-за защиты).источник
Допустимо:
Не законно:
Допустимо:
Не законно: (в отличие от ML)
источник
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
это новая строка)Я нашел этот пример из LYHFGG полезным:
let
- это выражение, поэтому вы можете поместитьlet
любое (!) место, куда могут идти выражения.Другими словами, в приведенном выше примере это не возможно использовать
where
просто заменитьlet
(без возможно использование некоторых более многословнымcase
выражения в сочетании сwhere
).источник
К сожалению, большинство ответов здесь слишком технические для новичка.
В LHYFGG есть соответствующая глава, которую вам следует прочитать, если вы еще этого не сделали, но по сути:
where
это просто синтаксическая конструкция (не сахар ), которая полезна только в определениях функций .let ... in
это само выражение , таким образом , вы можете использовать их везде , где вы можете поместить выражение. Само по себе выражение, оно не может использоваться для связывания вещей охранников.Наконец, вы также можете использовать
let
в списках:источник