反映Type参数

时间:2014-12-30 13:01:32

标签: reflection idris

我正在尝试创建一个函数

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

1 个答案:

答案 0 :(得分:3)

Idris中的反射是一种纯语法,仅编译时的功能。要预测它将如何工作,您需要了解Idris如何将您的程序转换为其核心语言。重要的是,您无法在运行时获得反映的术语,并像使用Lisp一样重建它们。以下是您的程序编译方式:

  1. 在内部,伊德里斯创造了一个洞,可以期待Type -> TT类型的东西。
  2. 在此状态下运行foo的校对脚本。我们从没有假设和Type -> TT类型的目标开始。也就是说,构建的术语看起来像?rhs : Type => TT . rhs?foo : ty => body语法显示有一个名为foo的洞,其最终值将在body内可用。
  3. 步骤intro t创建一个参数为t : Type的函数 - 这意味着我们现在有一个像?foo_body : TT . \t : Type => foo_body这样的术语。
  4. 然后reflect t步骤通过右侧的术语填充当前的洞并将其转换为TT。该术语实际上只是对函数参数的引用,因此您得到变量t。与所有其他证明脚本步骤一样,reflect只能访问编译时直接可用的信息。因此,使用术语foo_body的反映来填充t的结果为P Bound (UN "t") (TType (UVar (-1)))
  5. 如果你能在这里做你想做的事,那么对于理解Idris代码和有效运行它会产生重大影响。

    理解的缺失来自于无法使用参数化来推断基于类型的函数的行为。所有函数都会有效地成为ad-hoc多态,因为它们可以(比方说)在字符串列表上运行不同于在int列表上运行。

    性能损失来自于表示足够的类型信息来进行反射。在编译Idris代码之后,其中不存在类型信息(与诸如JVM或.NET之类的系统或诸如Python之类的动态类型系统不同,其中类型具有代码可以访问的运行时表示)。在Idris中,类型可能非常大,因为它们可以包含任意程序 - 这意味着必须维护更多的信息,并且在类型级别进行的计算也必须在运行时保留并重复。

    如果您想在编译时反思类型的结构以进一步证明自动化,请查看applyTactic策略。它的参数应该是一个反映上下文和目标的函数,并返回一个新的反射策略脚本。可以看到一个例子in the Data.Vect source

    所以我认为总结是伊德里斯不能做你想做的事情,而且可能永远都做不到,但你可能会以另一种方式取得进步。