了解Agda中的unquoteDecl

时间:2017-03-31 16:25:16

标签: agda

我正在尝试理解Agda内置的反射机制,所以我决定编写一个简单的函数,它接受一个字符串作为标识符, 引用的类型和引用的术语,并简单地使用给定的字符串标识符定义给定类型的术语。因此,我写了以下内容:

testDefineName' : String → TC Type → TC Term → TC ⊤
testDefineName' s t a =
   bindTC (freshName s)
     (λ n → bindTC t
     (λ t' → bindTC a
     (λ a' → (bindTC (declareDef (arg (arg-info visible relevant) n) t')
     (λ _ → defineFun n ((clause [] a') ∷ []))))))

unquoteDecl = (testDefineName' "test" (quoteTC ℕ) (quoteTC zero))

这种类型检查,但是,当我尝试在其他地方使用“test”时,我收到Not in scope: test错误。

unquoteDecl的{​​{3}}有点不透明。适当的声明应该是

的形式
unquoteDecl x_1 x_2 ... x_n = m

其中x_iName,而m的类型为TC \top,所以也许我试图做的事实际上是不可能的,但我仍然不喜欢我不明白这种机制是如何工作的:如果m必须是TC ⊤类型,因此不能是名称x_1 x_2 ... x_n的函数,我看不出它是如何可能的使用unquoteDecl将任何新名称纳入范围!

所以,总结一下:

是否可以使用Agda的反射机制定义类似我的函数,以便我可以使用String参数将新名称带入范围?我想要的是:

<boilerplate code for unquoting> testDefineName' "test" (quoteTC ℕ) (quoteTC zero)
test' : ℕ
test' = test

编译(即我实际上可以使用新名称“test”)

如果没有,m可以通过什么机制使用名称x_1 ... x_nm实际上有List Name → TC ⊤这样的类型,与文档相反吗?

1 个答案:

答案 0 :(得分:3)

基于the way Ulf uses unquoteDecl,我的印象是您需要在LHS上列出将扩展范围的名称。

您的设置问题在于,当您从Name生成新的String并且无法获取AFAIK时,您不会知道freshName。我的印象是testDefineName'仅用于从策略中生成内部名称。

如果你NameString而不是testDefineName' : Name → TC Type → TC Term → TC ⊤ testDefineName' n t a = bindTC t $ λ t' → bindTC a $ λ a' → bindTC (declareDef (arg (arg-info visible relevant) n) t') $ λ _ → defineFun n ((clause [] a') ∷ []) unquoteDecl test = testDefineName' test (quoteTC ℕ) (quoteTC zero) ,那么一切都会成功:

mocha