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.

下一篇: Haskell type family instance with type constraints