Haskell 'let' реализация
Чтение документации на Haskell.Happy и реализация оператора let
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 p):p) }
в документах говорится, что это "функция, которая принимает окружение значений переменных и возвращает вычисленное значение выражения:"
не может понять действительный смысл синтаксиса, как эти конструкции называются в Haskell?
Изменить: я имею в виду эти
\p -> $6 (($2,$4 p):p)
2 ответа
let
выражение в ML-подобных языках (таких как Haskell) просто вводит привязку локальной переменной:
magnitude x y =
let xs = x * x in
let ys = y * y in
sqrt (xs + ys)
В документах Happy говорится о реализации синтаксического анализатора для гипотетического языка, похожего на ML. $n
Переменные в синтаксисе Happy относятся к индексам вещей, которые соответствуют текущему правилу:
let var '=' Exp in Exp
1 2 3 4 5 6
Выражение в фигурных скобках - это код, который генерируется при совпадении этого правила.
Так \p -> $6 (($2,$4 p):p)
дает вам лямбду, которая принимает переменную среду p
, который представляет собой список пар имен и значений. Тело лямбды состоит из второго разобранного выражения ($6
) оценивается в p
плюс связь между именем ($2
) и значение, полученное в результате анализа первого проанализированного выражения ($4
) в текущих условиях ($4 p
).
В основном, среда p
такие как [("x",4),("y",5)]
определяет значения для переменных x
а также y
, Когда вы оцениваете выражение, которое может включать такие переменные, результат зависит от p
, Это представлено \p -> ...
,
Например, мы можем ожидать что-то вроде
Exp + Exp { \p -> $1 p + $2 p }
выражая тот факт, что оба термина оцениваются с использованием тех же значений переменных, как определено p
,
Сейчас, let
является своеобразным, потому что он определяет новую переменную, давая ей значение. Чтобы выразить этот факт, нам нужно изменить p
дополняя это новой ассоциацией.
let var = Exp in Exp
$1 $2 $3 $4 $5 $6
Дано p
, значение $4 просто $4 p
как мы делали в предыдущем примере суммы (мы предполагаем, что var
в 4 доллара не видно, то есть мы не разрешаем var
быть рекурсивно определенным). Написать
value_of_$4 = $4 p
Тем не менее, стоимость 6 долларов не $6 p
так как $6 должен "увидеть" только что определенный var
, Итак, мы пишем
value_of_$6 = $6 (p augmented with the association <<var = value_of_$4>>)
то есть
value_of_$6 = $6 ( ($2,value_of_$4) : p )
то есть
value_of_$6 = $6 ( ($2, $4 p) : p )
Таким образом, мы в конечном итоге
let var = Exp in Exp { \p -> $6 ( ($2, $4 p) : p ) }
$1 $2 $3 $4 $5 $6