阅读 Haskell.Happy 文档并实现 'let' 运算符
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 p):p) }
文档说它是“一个接受变量值环境并返回表达式计算值的函数:”
无法理解语法的实际含义,这些构造在 Haskell 中是如何调用的?
编辑:我的意思是这些
\p -> $6 (($2,$4 p):p)
let
类似 ML 的语言(例如 Haskell)中的表达式只是引入了局部变量绑定:
magnitude x y =
let xs = x * x in
let ys = y * y in
sqrt (xs + ys)
Happy 文档正在讨论为假设的类 ML 语言实现解析器。Happy 语法中的$n
变量指的是当前规则中匹配的事物的索引:
let var '=' Exp in Exp
1 2 3 4 5 6
花括号中的表达式是该规则匹配时生成的代码。
所以\p -> $6 (($2,$4 p):p)
给你一个 lambda,它接受一个变量 environment p
,它是一对名称和值的列表。lambda 的主体由在 中$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
就像我们在前面的 sum 示例中所做的一样(我们假设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