我对此事有疑问.
如果我有这种类型:
data Person = Person {name :: String, age :: Int}
data Example = Constructor1 Integer | Constructor2 Person
Run Code Online (Sandbox Code Playgroud)
我想为Example实例化Eq类
instantiate Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 ==e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2
Run Code Online (Sandbox Code Playgroud)
我们可以假设我已经为Person实例化了Eq类,所以我可以将Person与Person进行比较.
这是实例化具有多个构造函数的类的方法吗?
还有其他疑问.我应该在Constructor1和Constructor2之间添加一个比较.我不这么认为,因为他们可能来自不同的类型.
我在谈论类似这样的东西:
(==) (Constructor1 e1) (Constructor2 e2) == "no idea how to compare Person with Int"
Run Code Online (Sandbox Code Playgroud)
谢谢!
我应该在Constructor1和Constructor2之间添加一个比较吗?
你必须,否则你的实施Eq将是不完整的.
完成所有案例后,只需添加即可
(==) _ _ = False
Run Code Online (Sandbox Code Playgroud)
我不这么认为,因为他们可能来自不同的类型.
但它们属于同一类型,它们都是Example价值观.
所以你的Eq功能需要能够比较它们.
如果你认为在某些条件下拥有a Constructor1 number和a Constructor2 person是有意义的话,你可以编写适当的谓词来做到这一点.但这似乎不寻常,你应该为这种比较而不是使用你自己的类型类Eq.如果使用Eq,请确保它满足反射性,传递性和对称性.
还要注意,对于"无聊"的机制Eq实例,编译器可以自动派生它们(并且它会创建你想要编写的相同的东西):
data Example = Constructor1 Integer | Constructor2 Person
deriving Eq
Run Code Online (Sandbox Code Playgroud)
你也可以派生出来Show.
https://www.reddit.com/r/haskell/comments/28gxxz/how_does_deriving_eq_work/
我应该在
Constructor1和之间加一个比较Constructor2.我不这么认为,因为他们可能来自不同的类型.
嗯,这当然取决于你,你可以指定Constructor1 i等于给Constructor2 p定的age p == fromIntegral i,所以这Constructor1基本上保持一个"年龄"并且Constructor2相等于给定该年龄的构造函数具有该年龄,但这取决于你认为的两个平等Example的.只要您的函数满足等价关系条件就没有问题.
如果您不希望任何Constructor1对象等于Constructor2,则应添加False在该情况下返回的行:
instance Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 == e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2
(==) _ _ = FalseRun Code Online (Sandbox Code Playgroud)
但是你可以在特定情况下省去麻烦,只需写下:
data Example = Constructor1 Integer | Constructor2 Person deriving EqRun Code Online (Sandbox Code Playgroud)
然后Haskell instance Eq自动实现,其中两个Example对象被认为是相等的,因为数据构造函数是相同的,并且所有参数都相等.在所有其他情况下,这两个对象被认为是不相等的.