我试图更好地理解Haskell中的类和示例。因此,我正在研究:
http://learnyouahaskell.com/making-our-own-types-and-typeclasses
在这里,他们建议尝试:
instance (Eq m) => Eq (Maybe m) where
Just x == Just y = x == y
Nothing == Nothing = True
_ == _ = False
但是,当我这样做时,我会得到以下输出:
tryouts.hs:58:10: error:
Duplicate instance declarations:
instance Eq m => Eq (Maybe m) -- Defined at tryouts.hs:58:10
instance Eq a => Eq (Maybe a) -- Defined in `GHC.Maybe'
1.我怎么能越过这一步,示例化我自己的类型类声明呢?
1.作者认为类前面的(Eq m) => Eq
对于约束示例的内容是很重要的,这与在类级别上约束示例的内容是明显不同的(例如)当您定义Eq
时。然而,我不确定我是否理解它们之间的区别。这可能是我不理解OOP中类型类和常规类之间的区别以及“继承"。
3条答案
按热度按时间2guxujil1#
1.我怎么能越过这一步,示例化我自己的类型类声明呢?
这个错误说明在模块中已经包含了这样的示例。实际上,它在语义上是完全相同的,正如我们在源代码中所看到的:
实现
Eq
的默认方式是,如果两个项的数据构造函数相同,并且参数在元素方面相等,则返回True
。您可以定义自己的类型,然后定义示例,例如:
作者认为类前面的
(Eq m) => Eq
对于约束示例的内容是很重要的,这与在类级别上进行约束有明显的不同(例如)当你定义Eq.时,我不确定我是否理解它们的区别。这可能是我不理解OOP中类型类和常规类之间的区别以及“继承”的本质的原因。对于前者。如果您要用途:
那么它就意味着
Eq (Maybe a)
会隐含Eq a
,所以它是相反的。然而这是行不通的,因为如果Eq (Maybe Int)
是一个示例,那么Eq Int
也是一个示例,但是Eq Int
只能是一个示例,如果Int ~ f a
(Int
与f a
的型别相同),而a
是Eq
的执行严修。k4aesqcs2#
1.您不能真正地为
Maybe a
“重新定义”Eq
,因为它已经在Prelude中定义了。也就是说,可能有一种方法可以通过{-#LANGUAGE NoImplicitPrelude #-}
重新定义它,并小心地导入足够的类型和类型类,以避免导入包含Maybe a
的Eq
定义的文件。或者您可以使用其中一个pragma来允许重叠声明,但我对此并不熟悉,所以不要相信我的话。Eq m => Eq (Maybe m)
意味着为了使Maybe m
成为Eq
类型类的示例,m
必须已经是Eq
的示例。这是很自然的,因为为了比较Just a
和Just b
,你需要能够比较a
和b
。因此,您无法比较Just (+)
和Just (-)
等的相等性。zsohkypk3#
另一种方法是尝试使用默认从
Prelude
导入的内容--使用hiding
。在这种情况下,它可以看起来像这样: