Q 型
Language.Haskell.TH.Syntax
中定义的 Q :: * -> *
类型构造函数是一种抽象类型,表示可以访问运行计算的模块的编译时环境的计算。Q
类型也处理可变替换,称为 TH 的名称捕获 (在此讨论。)所有接头都有一些 Q X
用于某些 X
。
编译时环境包括:
- 范围内标识符和有关所述标识符的信息,
- 功能类型
- 构造函数的类型和源数据类型
- 类型声明的完整规范(类,类型系列)
- 发生拼接的源代码(行,列,模块,包)中的位置
- 功能的固定性(GHC 7.10)
- 启用 GHC 扩展(GHC 8.0)
Q
类型还具有生成新名称的功能,功能 newName::String -> Q Name
。请注意,该名称不是隐式绑定的,因此用户必须自己绑定它,因此确保使用该名称的结果是用户的责任。
Q
有 Functor,Monad,Applicative
的实例,这是操作 Q
值的主界面,以及 Language.Haskell.TH.Lib
中提供的组合器,它们为形式的 TH ast 的每个构造函数定义一个辅助函数:
LitE::Lit -> Exp
litE::Lit -> ExpQ
AppE::Exp -> Exp -> Exp
appE::ExpQ -> ExpQ -> ExpQ
注意,ExpQ
,TypeQ
,DecsQ
和 PatQ
是 AST 类型的同义词,它们通常存储在 Q
类型中。
TH 库提供了一个函数 runQ::Quasi m => Q a -> m a
,并且有一个实例 Quasi IO
,所以看起来 Q
类型只是一个花哨的 IO
。但是,runQ::Q a -> IO a
的使用产生了一个 IO
动作,它无法访问任何编译时环境 - 这只能在实际的 Q
类型中使用。如果尝试访问所述环境,此类 IO
操作将在运行时失败。