C.
塞古拉角
Torrano/
理论计算机科学电子笔记
177
(
2007
)
201
这个机制建立在一元库之上。引用monadQ将元编程特性封装为新名称生成。它
是IO
monad
的一个扩展。通常的一元运算符bind,
return
和
fail
都是可用的,还有
do-notation [19]
。函数runQ使Q
monad
内的抽象语法树可用于IO
monad
,例如用于
打印。这就是我们需要知道的关于引用单子的一切。
引用的
Haskell
代码的翻译使其抽象语法树
作为
ExpQ
类型的值可用,其中类
型ExpQ =
Q
Exp
;
例如。
的|\x->x|]::ExpQ。
TH提供语法构造函数
建 立 在 引 用 单 子 之 上 它 们 的 名 字 类 似 于 代 数 数 据 类 型 的 构 造 函 数 , 例 如
lamE
::
[PatQ] ->
ExpQ
->
ExpQ。例如,我们可以构建表达式
[|\x->x|]
也可以
写lamE
[varP
(mkName
“x”)]
(varE
(mkName
“x”)),
其中mkName::
String
->
Name。
计算可以在编译时通过拼接符号$进行。它在编译时评估其内容(ExpQ类型),
将生成的抽象语法树转换为
Haskell
代码,并将其插入程序中的调用位置。例如,
[|\x->$qe|]
在编译 时计算qe, 计算的结果, 一个Haskell表达式qe' , 被 拼 接 到
lambda 抽象 中,给出
[|\x->qe'|]中。
我们将在第
4
节中使用准引用机制来分析和
转换Haskell程序,并使用拼接符号
来在编译
时完成这一工作。一个漂亮的打印库Language.Haskell.TH.PprLib将有助
于可视化我们示例的结果
我们在这里没有使用Template Haskell的其他功能;感兴趣的读者可以查看[17,
18]以获得更多细节。
3
不确定性分析与信案转换
3.1
动机
像Haskell这样的函数式语言的实际实现使用按需调用的参数传递机制。一个参数只
有在函数体中使用时才被求值;一旦它被求值为弱头范式,它就会被更新为新值,这
样后续对该参数的访问就不会从头开始求值。这种机制的实现为实际参数构建了一
个闭包或挂起,并在评估时进行更新。由
let
表达式绑定的变量也会发生同样的情
况:
当主表达式需要它的值时,它被求值并随后被更新。
精确性分析
[9
,
1
,
20
,
2]
检测将由函数体评估的参数。在这种情况下,可以避
免闭合结构,并且可以立即进行评估。这意味着按需调用被按值调用取代。
同样的分析可以用来检测那些由
let
表达式绑定的变量,这些变 量 将由
l e t
的主表
达式
求值。
这些变量可以是