我对此事有疑问。
如果我有这种类型:
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"
谢谢!
答案 0 :(得分:7)
是否应该在Constructor1和Constructor2之间添加比较?
您必须这样做,否则您对Eq
的实现将是不完整的。
在所有情况下,只需添加
(==) _ _ = False
我不这么认为,因为它们可能来自不同的类型。
但是它们是同一类型,它们都是Example
值。
因此您的Eq
函数需要能够比较它们。
如果您认为在某些情况下让Constructor1 number
和Constructor2 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)
我应该在
Constructor1
和Constructor2
之间添加一个比较。我不这么认为,因为它们可能来自不同的类型。
当然,取决于您,您可以指定Constructor1 i
等于Constructor2 p
,age 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
会引发异常(True
和False
是Bool
类型的不同构造函数),"hello" == ""
(""
就是{{ 1}}(类型为[]
)和[Char]
为"hello"
,因此您又拥有不同的构造函数('h' : "ello"
和[]
)。
您可以这样做:
: