我正在尝试创建一个函数
import Language.Reflection
foo : Type -> TT
我使用reflect
策略尝试了它:
foo = proof
{
intro t
reflect t
}
但这反映在变量t
本身上:
*SOQuestion> foo
\t => P Bound (UN "t") (TType (UVar 41)) : Type -> TT
答案 0 :(得分:3)
Idris中的反射是一种纯语法,仅编译时的功能。要预测它将如何工作,您需要了解Idris如何将您的程序转换为其核心语言。重要的是,您无法在运行时获得反映的术语,并像使用Lisp一样重建它们。以下是您的程序编译方式:
Type -> TT
类型的东西。foo
的校对脚本。我们从没有假设和Type -> TT
类型的目标开始。也就是说,构建的术语看起来像?rhs : Type => TT . rhs
。 ?foo : ty => body
语法显示有一个名为foo
的洞,其最终值将在body
内可用。intro t
创建一个参数为t : Type
的函数 - 这意味着我们现在有一个像?foo_body : TT . \t : Type => foo_body
这样的术语。reflect t
步骤通过右侧的术语填充当前的洞并将其转换为TT
。该术语实际上只是对函数参数的引用,因此您得到变量t
。与所有其他证明脚本步骤一样,reflect
只能访问编译时直接可用的信息。因此,使用术语foo_body
的反映来填充t
的结果为P Bound (UN "t") (TType (UVar (-1)))
。如果你能在这里做你想做的事,那么对于理解Idris代码和有效运行它会产生重大影响。
理解的缺失来自于无法使用参数化来推断基于类型的函数的行为。所有函数都会有效地成为ad-hoc多态,因为它们可以(比方说)在字符串列表上运行不同于在int列表上运行。
性能损失来自于表示足够的类型信息来进行反射。在编译Idris代码之后,其中不存在类型信息(与诸如JVM或.NET之类的系统或诸如Python之类的动态类型系统不同,其中类型具有代码可以访问的运行时表示)。在Idris中,类型可能非常大,因为它们可以包含任意程序 - 这意味着必须维护更多的信息,并且在类型级别进行的计算也必须在运行时保留并重复。
如果您想在编译时反思类型的结构以进一步证明自动化,请查看applyTactic
策略。它的参数应该是一个反映上下文和目标的函数,并返回一个新的反射策略脚本。可以看到一个例子in the Data.Vect
source。
所以我认为总结是伊德里斯不能做你想做的事情,而且可能永远都做不到,但你可能会以另一种方式取得进步。