Haskell 不同EDSL之间的转换(不同类型类约束)
我正在尝试将一个简单的eDSL“编译”成这种语言。这里出现的一个问题是,我的类型/函数上的类型类约束与Atom语言的约束不匹配 编译成Atom的一个eDSL是,它也有同样的问题,它以一种相当冗长的方式解决了这个问题。以下是所涉及数据类型的简化版本:Haskell 不同EDSL之间的转换(不同类型类约束),haskell,Haskell,我正在尝试将一个简单的eDSL“编译”成这种语言。这里出现的一个问题是,我的类型/函数上的类型类约束与Atom语言的约束不匹配 编译成Atom的一个eDSL是,它也有同样的问题,它以一种相当冗长的方式解决了这个问题。以下是所涉及数据类型的简化版本: {-# LANGUAGE GADTs #-} data Type a where TFloat :: Type Float data Op1 a b where Neg :: Type a -> Op1 a a cl
{-# LANGUAGE GADTs #-}
data Type a where
TFloat :: Type Float
data Op1 a b where
Neg :: Type a -> Op1 a a
class NumE a where
instance NumE Float
data Exp e where
ENeg :: NumE a => Exp a -> Exp a
Type
和Op1
是新eDSL的一部分,NumE
和Exp
属于编译目标。要在某个点在EDSL之间转换,我需要一个具有以下类型的函数op2exp
:
op2exp :: Op1 a b -> Exp a -> Exp b
现在Atom处理这个问题的方式是:
这是可行的,但相当麻烦,而且充满了重复
问题:
有没有一种方法,可以使用新的语言功能,以更简单的方式编写op2exp
函数?理想情况下,应遵循以下原则:
op2exp (Neg t) = ENeg
理想情况下,我甚至不需要
类型
数据类型,让编译器找出所有类型都匹配。您可以使用*->Constraint
类型参数,在目标语言中使Op1
数据类型参数化。看看Atom和Ivory库,我认为类似的东西应该可以工作:
{-# LANGUAGE GADTs, ConstraintKinds #-}
data Op1 expr a b where
Neg :: (expr a, Num a) => Op1 expr a a
class AtomExpr a where
instance AtomExpr Float
data AtomExp e where
ENeg :: (AtomExpr a, Num a) => AtomExp a -> AtomExp a
op2exp :: Op1 AtomExpr a b -> AtomExp a -> AtomExp b
op2exp Neg = ENeg
您的理想实现在GHC 7.6.1Oh中为我编译,您是对的。
Neg
的参数当然应该是一个变量。我改变了问题。如果你试图编译它,你会得到这样一个错误:无法推断(numeb)是由使用ENeg产生的,这正是NumEInst
解决的问题。你不能在Neg
构造函数中用numea=>
替换类型a->
吗?我不想,因为也许将来我会想编译成一个不同的eDSL(也就是说,看起来很有趣),就像copilot和Atom一样。
{-# LANGUAGE GADTs, ConstraintKinds #-}
data Op1 expr a b where
Neg :: (expr a, Num a) => Op1 expr a a
class AtomExpr a where
instance AtomExpr Float
data AtomExp e where
ENeg :: (AtomExpr a, Num a) => AtomExp a -> AtomExp a
op2exp :: Op1 AtomExpr a b -> AtomExp a -> AtomExp b
op2exp Neg = ENeg