Я новичок в 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.
f = body where x = xbody; y = ybody ...
означаетf = let x = xbody; y = ybody ... in body
case .... of ... where
выражение? Я не уверен в этом.
let
и ,where
когда я впервые начал изучать Haskell. Я думаю, что лучший способ понять это - понять, что между ними очень мало различий, и поэтому не о чем беспокоиться. Значениеwhere
дано в терминахlet
очень простого механического преобразования. См. Haskell.org/onlinereport/decls.html#sect4.4.3.2 На самом деле это преобразование существует только для удобства записи.