我正在关注这篇博文:http ://semantic-domain.blogspot.com/2012/12/total-functional-programming-in-partial.html
它展示了一个用于System T(一种简单的全功能语言)的小型 OCaml 编译器程序。
整个管道采用 OCaml 语法(通过 Camlp4 元编程)将它们转换为 OCaml AST,然后再转换为 SystemT Lambda Calculus(参见module Term
:),最后是 SystemT Combinator Calculus(参见:)
module Goedel
。最后一步也用 OCaml 元编程Ast.expr
类型包装。
我试图在不使用 Template Haskell 的情况下将其翻译成 Haskell。
对于 SystemT Combinator 表单,我将其写为
{-# LANGUAGE GADTs #-}
data TNat = Zero | Succ TNat
data THom a b where
Id :: THom a a
Unit :: THom a ()
ZeroH :: THom () TNat
SuccH :: THom TNat TNat
Compose :: THom a b -> THom b c -> THom a c
Pair :: THom a b -> THom a c -> THom a (b, c)
Fst :: THom (a, b) a
Snd :: THom (a, b) b
Curry :: THom (a, b) c -> THom a (b -> c)
Eval :: THom ((a -> b), a) b -- (A = B) * A -> B
Iter :: THom a b -> THom (a, b) b -> THom (a, TNat) b
请注意,这Compose
是前向合成,不同于(.)
.
在 SystemT Lambda Calculus 到 SystemT Combinator Calculus 的转换过程中,该Elaborate.synth
函数尝试将 SystemT Lambda 演算变量转换为一系列组合投影表达式(与 De Brujin 指数相关)。这是因为组合演算没有变量/变量名称。这是通过Elaborate.lookup
which 使用Quote.find
函数来完成的。
问题是我将组合微积分编码为 GADT THom a b
。翻译Quote.find
函数:
let rec find x = function
| [] -> raise Not_found
| (x', t) :: ctx' when x = x' -> <:expr< Goedel.snd >>
| (x', t) :: ctx' -> <:expr< Goedel.compose Goedel.fst $find x ctx'$ >>
进入哈斯克尔:
find :: TVar -> Context -> _
find tvar [] = error "Not Found"
find tvar ((tvar', ttype):ctx)
| tvar == tvar' = Snd
| otherwise = Compose Fst (find tvar ctx)
导致无限类型错误。
• Occurs check: cannot construct the infinite type: a ~ (a, c)
Expected type: THom (a, c) c
Actual type: THom ((a, c), c) c
问题源于这样一个事实,即使用和Compose
来自GADT会导致类型签名的无限变化。Fst
Snd
THom a b
该文章没有这个问题,因为它似乎使用Ast.expr
OCaml 东西来包装底层表达式。
我不确定如何在 Haskell 中解决。我应该使用存在量化的类型,例如
data TExpr = forall a b. TExpr (THom a b)
或者某种类型级别Fix
来适应无限类型问题。但是我不确定这如何改变find
orlookup
功能。