模板 Haskell:为具有类型 class 约束的函数签名生成代码

Template Haskell: generating code for a function signature with the type class constraints

我需要为具有类型 class 约束的函数签名生成代码,例如:

fun :: (Ord a) => a -> a

我正在使用以下签名构造函数:

SigD Name Type 

所以,我需要生成一个类型。我最好的猜测是使用以下构造函数:

ForallT [TyVarBndr] Cxt Type

它对应于以下声明(见Temaplate Haskell documentation):

forall <vars>. <ctxt> => <type>

但是 Cxt 只是 Type 列表的同义词,我找不到合适的 Type 构造函数来生成类型 class 约束。我应该怎么做才能为类型 class 约束生成代码?

我相信,正如评论中提到的,TH 没有区分 Types 和 Constraints(哪一种是有道理的,尤其是现在 ConstraintKinds 左右)。我通常发现,在使用 TH 生成代码时,检查准引用的 AST 是否有一个具体的、具体的例子,无论我试图实现什么,准引用都不够好。例如,在 GHCI 中:

λ> :set -XTemplateHaskell
λ> import Language.Haskell.TH
λ> runQ $ [d|f :: Ord a => a -> a; f = id|]
[SigD f_1 (ForallT [] [AppT (ConT GHC.Classes.Ord) (VarT a_0)] (AppT (AppT ArrowT (VarT a_0)) (VarT a_0))),ValD (VarP f_1) (NormalB (VarE GHC.Base.id)) []]

这表明约束部分只是 Name for Ord 应用于您用于类型变量的名称。请注意,至少在这个级别,ForallT 参数列表是空的,因为类型签名中的 a 没有写成显式的 forall a..