如何在Haskell中定义DSL中的类型?

时间:2017-01-27 05:31:38

标签: haskell functional-programming abstract-syntax-tree dsl gadt

我一直在编写一个AST来在Haskell中构建DSL,为此,我使用GADT来定义表达式,例如:

data Expr a where
    I   :: Int  -> Expr Int
    B   :: Bool -> Expr Bool
    Add :: Expr Int -> Expr Int -> Expr Int
    Mul :: Expr Int -> Expr Int -> Expr Int
    Eq  :: Expr Int -> Expr Int -> Expr Bool

但是,我想像Add和Mul这样的表达式也可以使用Float和Double类型的其他数值。 我怎样才能取得这样的成绩?

1 个答案:

答案 0 :(得分:1)

您可以稍微概括Expr并使用

data Expr a where
  Lit :: a -> Expr a                           -- why not just let anything in?
  Add :: Num a => Expr a -> Expr a -> Expr a   -- only `a` w/ `Num a` can be added
  Mul :: Num a => Expr a -> Expr a -> Expr a   -- only `a` w/ `Num a` can be multiplied
  Eq  :: Eq a => Expr a -> Expr a -> Expr Bool -- only `a` w/ `Eq a` can be added

然后,问题实际上是:你想用它做什么?如果你只是想显式构造一个类型检查的AST,然后能够对它进行评估,那么上面的工作就可以了。

eval :: Expr a -> a
eval (Lit x) = x
eval (Add x y) = eval x + eval y
eval (Mul x y) = eval x * eval y
eval (Eq x y) = eval x == eval y