如何使用不同的构造函数 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 进行比较。

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

和其他疑问。我应该在构造函数 1 和构造函数 2 之间添加比较吗?我不这么认为,因为他们可能来自不同的类型。

我说的是这样的东西:

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

谢谢!

我应该在 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/

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

好吧,这当然取决于您,您可以指定Constructor1 i等于给定该age p == fromIntegral iConstructor2 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会抛出一个异常(TrueFalseBool类型的不同构造函数(,"hello" == ""也会抛出异常(""[](在类型[Char](和"hello"'h' : "ello",所以你又有不同的构造函数([]:((。

你可以这样做:

instance Eq Example where
(==) (Constructor1 e1) (Constructor1 e2) = e1 == e2
(==) (Constructor2 e1) (Constructor2 e2) = e1 == e2
(==) _ _ = False

最新更新