我一直在编写一个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类型的其他数值。 我怎样才能取得这样的成绩?
答案 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