我正在尝试理解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_i
为Name
,而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_n
? m
实际上有List Name → TC ⊤
这样的类型,与文档相反吗?
答案 0 :(得分:3)
基于the way Ulf uses unquoteDecl
,我的印象是您需要在LHS上列出将扩展范围的名称。
您的设置问题在于,当您从Name
生成新的String
并且无法获取AFAIK时,您不会知道freshName
。我的印象是testDefineName'
仅用于从策略中生成内部名称。
如果你Name
取String
而不是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