从GADT中获得一个简单的Eq类

时间:2016-10-05 15:26:43

标签: haskell typeclass gadt

我认为GADT很棒,直到我尝试用GADTs"表达任何"表达式。分散在互联网上使用的例子。

传统的ADT以免费的方式提供定义平等。在GADT中代码:

data Expr a where
  (:+:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr a
  (:-:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr a
  (:*:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr a
  (:/:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr a
  (:=:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  (:<:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  (:>:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  (:>=:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  (:<=:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  (:<>:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool
  EOr :: Expr Bool -> Expr Bool -> Expr Bool
  EAnd :: Expr Bool -> Expr Bool -> Expr Bool
  ENot :: Expr Bool -> Expr Bool
  ESymbol :: (Show a, Eq a) => String -> Expr a
  ELiteral :: (Show a, Eq a) => a -> Expr a
  EFunction :: (Show a, Eq a) => String -> [Expr a] -> Expr a
  deriving (Eq)

我得到(非常可以理解):

    • Can't make a derived instance of ‘Eq (Expr a)’:
        Constructor ‘:+:’ has existentials or constraints in its type
        Constructor ‘:-:’ has existentials or constraints in its type
        Constructor ‘:*:’ has existentials or constraints in its type
        Constructor ‘:/:’ has existentials or constraints in its type
        Constructor ‘:=:’ has existentials or constraints in its type
        Constructor ‘:<:’ has existentials or constraints in its type
        Constructor ‘:>:’ has existentials or constraints in its type
        Constructor ‘:>=:’ has existentials or constraints in its type
        Constructor ‘:<=:’ has existentials or constraints in its type
        Constructor ‘:<>:’ has existentials or constraints in its type
        Constructor ‘EOr’ has existentials or constraints in its type
        Constructor ‘EAnd’ has existentials or constraints in its type
        Constructor ‘ENot’ has existentials or constraints in its type
        Constructor ‘ESymbol’ has existentials or constraints in its type
        Constructor ‘ELiteral’ has existentials or constraints in its type
        Constructor ‘EFunction’ has existentials or constraints in its type
        Possible fix: use a standalone deriving declaration instead
    • In the data declaration for ‘Expr’

如果我没有为每个构造函数设置Eq限制,那么这是可以理解的,但现在我必须为所有这些构造函数编写琐碎的相等规则。

我觉得有更好的方法可以解决这个问题。

1 个答案:

答案 0 :(得分:8)

传统deriving无法处理GADT约束。原则上,独立派生可以:

{-# LANGUAGE GADTs, StandaloneDeriving #-}
data Expr a where
  (:+:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr a
  ...
deriving instance Eq (Expr a)

但是,这对您没有帮助,因为Eq实例是不可能的。你将如何比较

(1 :<: (2 :: Expr Int)) == (pi :<: (sqrt 2 :: Expr Double))

这是不可能的; GADT约束

  (:<:) :: (Show a, Eq a) => Expr a -> Expr a -> Expr Bool

只强制Expr 中的两个值具有相同的类型且Eq,但它并没有告诉您有关<的类型< em>不同的表达式。