3

我试图弄清楚类型类的目的,如果不使用类型类还有什么。

类型类是定义多态函数的一种方式吗?

类型类是定义多态函数的唯一方法吗?例如:

class Eq a where
    (==), (/=) :: a -> a -> Bool
    x /= y  =  not (x == y)

instance Eq Bool where 
    False == False  =  True 
    True  == True   =  True 
    _     == _      =  False

我可以在不使用 type class 的情况下定义==and /=for Bool(以及任何其他类型)Eq吗?

如果有任何其他方式,我什么时候应该使用哪种方式来定义多态函数,使用类型类还是使用其他方式?

4

3 回答 3

7

你总是可以编写不受约束的多态函数,它不需要任何类型类。一个简单的例子是

length :: [a] -> Int

– 这在没有类型类的情况下有效,并且(好吧,因为)它适用于任何类型 a。也就是说,length实际上并不关心该列表中的是什么,它只关心包含这些值的结构。它实际上从未对这些值本身做任何事情,而多态类型实际上保证了这一点。

如果您需要的多态任务是这种形式,即您实际上不需要访问的类型,您只知道它在那里,那么您不应该编写/调用类型类,只需使用 ML 风格的参数多态性,如length. 但是,您经常需要自己访问这些值,以某种方式检查它们。这样做不会限制您使用特定的具体类型,这就是类型类的用途。Eq,正如你自己引用的那样,就是一个例子。

于 2019-07-18T16:18:35.333 回答
6

类型类是定义多态函数的一种方式吗?

的,这是一种方式。但不是唯一的方法。例如,参数多态只是意味着如果你定义一个类似的函数init :: [a] -> [a],它将适用于任何a。类型类用于临时多态性:根据类型,实现可能完全不同。这与参数多态性相反,其中head函数始终相同,而不管a.

类型类是定义多态函数的唯一方法吗?

,请参阅上一节。

我可以在不使用 type class 的情况下定义==and /=for Bool(以及任何其他类型)Eq吗?

这取决于所有类型的实现是否相同。您可以使用该-XNoImplicitPrelude标志来避免导入Prelude,然后您可以定义自己的(==)函数。

于 2019-07-18T16:18:14.360 回答
5

OOP 和 haskell 中的多态函数之间存在差异,我之所以这么说是因为 OOP 中通常使用术语“多态”。

例如,列表上的函数是多态的:

cons:: a -> [a] -> [a]
cons x xs = x:xs

其中 a 是多态类型,并且那里没有类型类。

顺便说一句,有一种方法可以快速实现类型类,默认情况下,例如Eqor Show,例如:

data MBool = MTrue | MFalse deriving (Eq, Show)

所以,不同之处在于类型类是一个约束,想象一下这个带有列表的函数:

mapShow :: Show a =>  [a] -> [String]
mapShow = map show

那是不同的,因为现在,a 是受限制的,它不能是任何“a”。它应该实现 typeclass Show

总之,您可以看到函数a类型比函数 类型cons更通用或抽象。Show => a -> amapShow

于 2019-07-18T16:13:51.720 回答