不同eDSL之间的转换(不同类型类约束)

时间:2013-07-17 21:17:40

标签: haskell

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

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

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

TypeOp1是新eDSL的一部分,NumEExp属于编译目标。要在某些时刻在eDSL之间进行转换,我需要一个具有以下类型的函数op2exp

op2exp :: Op1 a b -> Exp a -> Exp b

现在,Atom处理此问题的方式是rather verbose

data NumEInst e = NumE e => NumEInst

numEInst :: Type a -> NumEInst a
numEInst TFloat = NumEInst

op2exp :: Op1 a b -> Exp a -> Exp b
op2exp op = case op of
    Neg t -> case numEInst t of NumEInst -> ENeg

这很有效,但是非常繁琐且充满重复。

问题:

有没有办法,使用新的语言功能,以更简单的方式编写op2exp函数?理想情况下是:

op2exp (Neg t) = ENeg

理想情况下,我甚至不需要Type数据类型,并让编译器确定所有类型都匹配。

1 个答案:

答案 0 :(得分:1)

您可以使用类型Op1的类型参数,使目标语言中的* -> Constraint数据类型参数化。看看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