Haskell类型和类型类声明

evrscar2  于 2022-11-14  发布在  其他
关注(0)|答案(3)|浏览(199)

我试图更好地理解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中类型类和常规类之间的区别以及“继承"。

2guxujil

2guxujil1#

1.我怎么能越过这一步,示例化我自己的类型类声明呢?
这个错误说明在模块中已经包含了这样的示例。实际上,它在语义上是完全相同的,正如我们在源代码中所看到的:

data  Maybe a  =  Nothing | Just a
  deriving ( Eq  -- ^ @since 2.01
           , Ord -- ^ @since 2.01
           )

实现Eq的默认方式是,如果两个项的数据构造函数相同,并且参数在元素方面相等,则返回True
您可以定义自己的类型,然后定义示例,例如:

data Maybe2 a = Nothing2 | Just2 a

instance Eq m => Eq (Maybe2 m) where  
    Just2 x == Just2 y = x == y  
    Nothing 2== Nothing2 = True  
    _ == _ = False

作者认为类前面的(Eq m) => Eq对于约束示例的内容是很重要的,这与在类级别上进行约束有明显的不同(例如)当你定义Eq.时,我不确定我是否理解它们的区别。这可能是我不理解OOP中类型类和常规类之间的区别以及“继承”的本质的原因。对于前者。
如果您要用途:

class Eq a => Eq (f a) where
    ...

那么它就意味着Eq (Maybe a)会隐含Eq a,所以它是相反的。然而这是行不通的,因为如果Eq (Maybe Int)是一个示例,那么Eq Int也是一个示例,但是Eq Int只能是一个示例,如果Int ~ f aIntf a的型别相同),而aEq的执行严修。

k4aesqcs

k4aesqcs2#

1.您不能真正地为Maybe a“重新定义”Eq,因为它已经在Prelude中定义了。也就是说,可能有一种方法可以通过{-#LANGUAGE NoImplicitPrelude #-}重新定义它,并小心地导入足够的类型和类型类,以避免导入包含Maybe aEq定义的文件。或者您可以使用其中一个pragma来允许重叠声明,但我对此并不熟悉,所以不要相信我的话。

  1. Eq m => Eq (Maybe m)意味着为了使Maybe m成为Eq类型类的示例,m必须已经是Eq的示例。这是很自然的,因为为了比较Just aJust b,你需要能够比较ab。因此,您无法比较Just (+)Just (-)等的相等性。
zsohkypk

zsohkypk3#

另一种方法是尝试使用默认从Prelude导入的内容--使用hiding。在这种情况下,它可以看起来像这样:

import Prelude hiding (Maybe, Just, Nothing)

data  Maybe a  =  Nothing | Just a

instance (Eq m) => Eq (Maybe m) where  
    Just x == Just y = x == y  
    Nothing == Nothing = True  
    _ == _ = False

相关问题