功能依赖/类型系列 - AST

时间:2010-12-10 02:59:01

标签: haskell types functional-dependencies type-families

最近我介绍了功能依赖和类型系列。对于一个类项目,我为Java和Haskell中的C子集编写(完成)了一个解释器。用于术语的评估函数的Haskell实现需要使用显式模式匹配和展开表示文字的值构造函数来构建“函数表”。一种不愉快的情况(但比Java更漂亮)。

在搜索了一段时间后,我遇到了“集合”示例,想知道我是否可以将其应用于我的抽象语法,以便为文字生成通用的“注入”和“项目自”函数。我想出了两个初步的测试尝试:

(使用函数依赖:注入和投影函数在没有显式类型注释的情况下工作, Lit 注入 lit 也是如此。但是,的投影函数点亮不会输入,错误“无法将预期类型l与推断类型l'匹配”。)

class Prim l a | l -> a, a -> l where
 inj  :: a -> l
 proj :: l -> a

instance Prim LB Bool where inj = LB; proj = lb
instance Prim LI Int  where inj = LI; proj = li

data LB = LB {lb :: Bool}
data LI = LI {li :: Int}

data E where Lit :: Prim l a => l -> E

lit :: Prim l a => l -> E
lit = Lit

unlit :: Prim l a => E -> l
unlit (Lit a) = a

(使用类型系列。这里的问题是我不能让Haskell从参数推断没有显式注释的正确返回类型,而且我不能编写泛型函数lit :: Val l -> E和{{1 }}。)

unlit :: E -> Val l

我不太了解类型系列,并且对功能依赖性有一个脆弱的把握。但是我想知道两件事:(a)我想要的功能是否可以输入和实现; (b)如果我误解了一些基本的东西。它几乎可以工作,但我现在已经和类型检查器争了一段时间了。

编辑这是我想要的简单模型,因为它不清楚。类class Show l => Prim l where type Val l :: * inj :: Val l -> l proj :: l -> Val l data LB a = LB {lb :: Bool} data LI a = LI {li :: Int } instance Prim (LB a) where type Val (LB a) = Bool; inj = LB; proj = lb instance Prim (LI a) where type Val (LI a) = Int; inj = LI; proj = li; data E where Lit :: Prim l => l -> E Bin :: Op -> E -> E -> E 基本上实现了我想要的功能。但我无法收集各种“可以包装和不可挽回的”价值,以便制作出一个AST。

Bin

2 个答案:

答案 0 :(得分:4)

定义Lit构造函数的方式将阻止您突出显示它包含的值,无论您如何定义投影函数。

让我们看一下构造函数的类型:

Lit :: Prim l => l -> E

类型变量l出现在参数中,但不出现在返回类型中。这意味着当你构造一个Lit时,你输入一个属于Prim成员的某种类型的值,然后永久地忘记它的类型

我不确定你想如何消除模式匹配和值构造函数的展开。对于如何进行预测,您基本上有两种选择:

  1. 运行时的项目值,使用模式匹配或与其等效的内容。
  2. 编译时的项目值,通过使用类型系统证明您拥有的数据类型等于您想要的数据类型。
  3. 有理由使用编译时证明,但看起来你没有任何这些原因。

答案 1 :(得分:1)

如果您仍想坚持多态E的想法。您可以使用多态函数:

withUnlit :: E -> (forall l . Prim l => l -> b) -> b
withUnlit (Lit a) f = f a

但你唯一可以做的事情(你给Prim l提供的特质)是:

showE :: E -> String
showE e = withUnlit e show

injproj。但除了使用Val l之外,您无法使用Data.Dynamic(如果这是我认为的那样)。