如何使用不同的构造函数Haskell实例化类型的Eq(或任何类)

时间:2018-10-21 10:49:30

标签: haskell

我对此事有疑问。

如果我有这种类型:

data Person = Person {name :: String, age :: Int} 

data Example = Constructor1 Integer | Constructor2 Person

我想实例化Eq类作为示例

instantiate Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 ==e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2

我们可以假设我已经实例化了Person的Eq类,因此可以将Person与Person进行比较。

这是实例化具有多个构造函数的类型的类的方法吗?

还有其他疑问。我应该在Constructor1和Constructor2之间添加一个比较。我不这么认为,因为它们可能来自不同的类型。

我说的是这样的东西:

(==) (Constructor1 e1) (Constructor2 e2) == "no idea how to compare Person with Int"

谢谢!

3 个答案:

答案 0 :(得分:7)

  

是否应该在Constructor1和Constructor2之间添加比较?

您必须这样做,否则您对Eq的实现将是不完整的。

在所有情况下,只需添加

(==) _ _ = False
  

我不这么认为,因为它们可能来自不同的类型。

但是它们是同一类型,它们都是Example值。

因此您的Eq函数需要能够比较它们。

如果您认为在某些情况下让Constructor1 numberConstructor2 person相等是有意义的,则可以编写适当的谓词来做到这一点。但这似乎很不寻常,您可能应该使用自己的类型类来进行这种比较,而不要使用Eq。如果您确实使用Eq,请确保其满足反射性,传递性和对称性。


还要注意,对于“无聊”的机械师Eq实例,编译器可以自动派生它们(它将创建与您无论如何都要写的东西一样的东西):

data Example = Constructor1 Integer | Constructor2 Person
  deriving Eq

您还可以派生Show

https://www.reddit.com/r/haskell/comments/28gxxz/how_does_deriving_eq_work/

答案 1 :(得分:5)

  

我应该在Constructor1Constructor2之间添加一个比较。我不这么认为,因为它们可能来自不同的类型。

当然,取决于您,您可以指定Constructor1 i等于Constructor2 page p == fromIntegral i等于Constructor1,这样Constructor2基本上拥有一个“年龄”并且Example等于给定构造函数的年龄,但取决于您考虑的两个相等的Constructor1。只要您的函数满足equivalence relation conditions,就没有问题。

如果您不希望任何Constructor2对象等于False,则在这种情况下,应添加一行返回instance Eq Example where (==) (Constructor1 e1) (Constructor1 e2) = e1 == e2 (==) (Constructor2 e1) (Constructor2 e2) = e1 == e2 (==) _ _ = False的行:

data Example = Constructor1 Integer | Constructor2 Person deriving Eq

但是在这种特定情况下,您可以省去麻烦,只需编写:

instance Eq

Haskell然后自动实现一个Example,其中,两个<{1}}对象在给定数据构造函数相同的情况下被认为是相等的,并且所有参数都是 equal < / em>。在所有其他情况下,这两个对象被认为相等。

答案 2 :(得分:3)

你为什么不做

data Example = Constructor1 Integer | Constructor2 Person
    deriving (Eq)

?然后,编译器将为您实例化Eq

如果要手动执行,则可以,应该添加一个案例来比较不同的构造函数。如果标准库没有执行此操作,则例如True == False会引发异常(TrueFalseBool类型的不同构造函数),"hello" == """"就是{{ 1}}(类型为[])和[Char]"hello",因此您又拥有不同的构造函数('h' : "ello"[])。

您可以这样做:

: