Haskell GADT typesafe评估者:不止一种类型的常数项。
我一直在通过一些使用类型安全评估器示例介绍GADT的Haskell教程。 许多评估人员都在布尔和Int类型上运行。 因此,具有函数(常量整数,常量布尔,加法,乘法和校验相等)的评估程序的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
我对这个例子大体上很满意,但我希望能够将常量常量类型定义为Int或Bool类型,而不是为Int和Bool分别设置条目。 这可能吗。
这似乎工作,如果我只是在我的GADT中使用Type变量而不是Int或Bool。
这使得上面的例子:
data Expr a where
Con :: t -> Expr t
Add :: Expr Int -> Expr Int -> Expr Int
Mul :: Expr Int -> Expr Int -> Expr Int
Eq :: Expr Int -> Expr Int -> Expr Bool
那么常量类型不够有限,因为我可以有一个常量列表输入或一个常量字符串/浮点数,我只希望常量是INT或Bool。
我想过使用TypeClasses(我认为)来解决这个问题,因为这似乎能够限制类型变量的“域”,例如使用“Ord”类会限制类型变量t可能采用的可能类型该线
Con :: Ord t => t -> Term t
不幸的是,我不知道如何编写我自己的类来做到这一点,以限制类型变量只是布尔型或整型。 这是否正确?
谢谢。
使用像你这样的约束的想法可以像这样实现:
class Constant a
instance Constant Int
instance Constant Bool
data Expr a where
C :: Constant a => a -> Expr a
Add :: Expr Int -> Expr Int -> Expr Int
Mul :: Expr Int -> Expr Int -> Expr Int
Eq :: Expr Int -> Expr Int -> Expr Bool
这将工作得很好,我猜
eval :: Expr a -> a
eval (C a) = a
eval (Add a b) = eval a + eval b
eval (Mul a b) = eval a * eval b
eval (Eq a b) = eval a == eval b
另一方面,如果你想匹配常量,你可以使用另一个GADT:
module SO where
data Const a where
ConstB :: Bool -> Const Bool
ConstI :: Int -> Const Int
data Expr a where
C :: Const a -> Expr a
Add :: Expr Int -> Expr Int -> Expr Int
Mul :: Expr Int -> Expr Int -> Expr Int
Eq :: Expr Int -> Expr Int -> Expr Bool
用法
λ> C (ConstB False)
C (ConstB False) :: Expr Bool
λ> C (ConstI 5)
C (ConstI 5) :: Expr Int
链接地址: http://www.djcxy.com/p/43141.html
上一篇: Haskell GADT typesafe Evaluator: Constant term for more than one type.