Haskell 不同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

我正在尝试将一个简单的eDSL“编译”成这种语言。这里出现的一个问题是,我的类型/函数上的类型类约束与Atom语言的约束不匹配

编译成Atom的一个eDSL是,它也有同样的问题,它以一种相当冗长的方式解决了这个问题。以下是所涉及数据类型的简化版本:

{-# 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