Haskell中Futamura投影的证据
我读过Dan Piponi在The Three Projections of Doctor Futamura上的优秀博客文章。在文章结尾处,他有一个附录,其中有Haskell中Futamura预测的证据。但是,我发现他的文章缺乏有关涉及语言的信息。为了使Futamura预测能够工作,专业人员必须具备哪些源语言,目标语言和对象语言?例如,如果我在Haskell中编写了一个Haskell到LLVM专家,那么Futamura预测会工作吗?如果你写了一个Haskell程序来证明这一点,就像Dan Piponi在他的文章中所做的那样,这将会很有帮助。Haskell中Futamura投影的证据
是的,当且仅当专家的源语言和对象语言相同时,Futamura投影才能工作。这是因为专家只能使用它可以读取的相同语言编写。但是,专业人员的目标语言是独立于其他两个人的。这具有重要的后果,我将在稍后的答案中讨论。
为了证明我的假设,我将引入一个新的表示法来基于tombstone diagrams松散地描述程序。墓碑图(或T图)是编译器和其他相关metaprograms的图形表示。它们用于说明和推理程序从源语言(T的左边)到目标语言(T的右边)的转换,如用对象语言(T的底部)实现的。让我们扩展T-图的想法,所有程序都:
α → β : ℒ -- A program is a function from α to β as implemented in language ℒ.
在元程序α
和β
的情况下,本身的程序:
(α → β :) × α → β : -- An interpreter for language as implemented in .
(α → β :) → (α → β :) : -- A compiler from to as implemented in .
(ι × α → β :) × ι → (α → β :) : -- A self-hosting specializer from to .
(ι × α → β :) → (ι → (α → β :) :) : -- A compiler compiler from to .
该符号可以直接转换成类型定义哈斯克尔。这个武装,我们现在可以写在Haskell的二村突出的证明相对于语言:
{-# LANGUAGE RankNTypes #-}
module Futamura where
newtype Program a b language = Program { runProgram :: a -> b }
type Interpreter source object = forall a b. Program (Program a b source, a) b object
type Compiler source target = forall a b. Program (Program a b source) (Program a b target) target
type Specializer source target = forall input a b. Program (Program (input, a) b source, input) (Program a b target) source
type Partializer source target = forall input a b. Program (Program (input, a) b source) (Program input (Program a b target) target) target
projection1 :: Specializer object target -> Interpreter source object -> Program a b source -> Program a b target
projection1 specializer interpreter program = runProgram specializer (interpreter, program)
projection2 :: Specializer object target -> Interpreter source object -> Compiler source target
projection2 specializer interpreter = runProgram specializer (specializer, interpreter)
projection3 :: Specializer source target -> Partializer source target
projection3 specializer = runProgram specializer (specializer, specializer)
我们使用RankNTypes
语言扩展隐藏式级别机制,使我们能够专注于所涉及的语言。对于自己应用专家也是必要的。
在上述程序中,第二个预测值得特别关注。它告诉我们,给定一个自承载的Haskell到LLVM专家,我们可以将它应用到任何用Haskell编写的解释器中,以获得一个LLVM编译器的源语言。这意味着我们可以用高级语言编写解释器,并使用它来生成一个针对低级语言的编译器。如果专家有什么用处,那么生成的编译器也会很好。
另一个值得注意的细节是自托管专家与自承载编译器非常相似。如果您的编译器已经执行了部分评估,那么将其转换为专门工具不应该太多。这意味着实施Futamura预测比原先认为的要容易得多,收益也大得多。我还没有测试过这个,所以拿着一粒盐。