在我试图决定是否在我的项目中使用EDSL时,我阅读了这篇论文和这篇论文,它们描述了meta-repa的实现。它们都提到了HOAS和FOAS。从第一篇论文中可以得知:
什么让
data FunC a where LitI :: Int -> FunC Int LitB :: Bool -> FunC Bool If :: FunC Bool -> FunC a -> FunC a -> FunC a While :: (FunC s -> s -> FunC Bool) -> (FunC s -> FunC s) -> FunC s -> FunC s Pair :: FunC a -> FunC b -> FunC (a, b) Fst :: FunC (a, b) -> FunC a Snd :: FunC (a, b) -> FunC b Prim1 :: String -> (a -> b) -> FunC a -> FunC b Prim2 :: String -> (a -> b -> c) -> FunC a -> FunC b -> FunC c Value :: a -> FunC a Variable :: String -> FunC a
We have also chosen Higher Order Abstract Syntax to represent constructs with variable binding. In the above data type, the only higher-order construct is
While
.
While
构造函数成为了HOAS?为什么其他构造函数都不是HOAS?在第二篇论文中,meta-repa代码写在一个HOAS树中,然后(在编译时)转换为FOAS以进行进一步处理。同样,我不明白在HOAS.hs中定义的数据是如何成为HOAS而在FOASTyped中定义的数据则是FOAS。来自那篇论文的神秘引用如下:
“类型
Expr
[在HOAS.hs中]使用高阶抽象语法来表示程序。这种表示对于编程很方便,但对于重写程序来说并不是最理想的。因此,AST被转换为第一阶段表示[.]可能的实现方式是跳过[HOAS] Expr
类型并直接生成第一阶段表示。我们保留了高阶表示部分原因是它有助于维护实现的类型安全性,部分原因是它允许我们编写一个良好类型化的无标签解释器。”是否存在一些通用的方法,使HOAS比FOAS更难转换?与FOAS相比,HOAS如何帮助实现类型安全?
我已经阅读了FOAS和HOAS的维基百科文章,但这并没有为我澄清任何问题。
维基百科认为HOAS在具有“变量绑定器”的语言中很有用(也在第一个引用中提到)。什么是变量绑定器,Haskell如何实现它,哪些语言没有变量绑定器?
->
比逻辑框架的函数空间要更加令人兴奋,因此它实际上并不是 HOAS。例如考虑Lam $ \ x -> case x of {Lam _ -> Unit; _ -> Unit :*: Unit}
,它根本不是一个 lambda 项。因为函数空间做的事情远不止变量绑定,所以您会包含一堆无意义的东西,以及实际的术语。LF 函数空间足够弱,HOAS 定义恰好给出了有意义的术语。 - pigworker