我对这件事有疑问。
如果我有此类型:
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 进行比较。
这是使用具有多个构造函数的类型实例化类的方法吗?
和其他疑问。我应该在构造函数 1 和构造函数 2 之间添加比较吗?我不这么认为,因为他们可能来自不同的类型。
我说的是这样的东西:
(==) (Constructor1 e1) (Constructor2 e2) == "no idea how to compare Person with Int"
谢谢!
我应该在 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/
我应该在
Constructor1
和Constructor2
之间添加比较吗?我不这么认为,因为他们可能来自不同的类型。
好吧,这当然取决于您,您可以指定Constructor1 i
等于给定该age p == fromIntegral i
Constructor2 p
,因此Constructor1
基本上持有一个"年龄"并且Constructor2
等于给定该人的年龄的构造函数具有该年龄,但这取决于您认为两个相等的Example
。只要你的函数满足等价关系条件,就没有问题。
如果不希望任何Constructor1
对象等于Constructor2
,则应添加一行在这种情况下返回False
:
instance Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 == e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2
(==) _ _ = False
但是在这种特定情况下,您可以省去麻烦,只需编写:
data Example = Constructor1 Integer | Constructor2 Personderiving Eq
然后,Haskell自动实现一个instance Eq
,其中两个Example
对象被认为是相等的,因为数据构造函数是相同的,并且所有参数都是相等的。在所有其他情况下,这两个对象被视为不相等。
你为什么不做
data Example = Constructor1 Integer | Constructor2 Person
deriving (Eq)
?然后编译器将为您实例化Eq
。
如果你想手动完成,那么是的,你应该添加一个案例来比较不同的构造函数。如果标准库没有这样做,那么例如True == False
会抛出一个异常(True
和False
是Bool
类型的不同构造函数(,"hello" == ""
也会抛出异常(""
是[]
(在类型[Char]
(和"hello"
是'h' : "ello"
,所以你又有不同的构造函数([]
和:
((。
你可以这样做:
instance Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 == e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2
(==) _ _ = False