什么时候应该通过类型类或其他方式定义多态函数?

时间:2019-07-18 16:07:48

标签: haskell polymorphism typeclass adhoc-polymorphism

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

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

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

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

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

是否可以在不使用类型类==的情况下为/=(和任何其他类型)定义BoolEq

还有其他方法时,什么时候应该使用类型类或其他方法来定义多态函数?

3 个答案:

答案 0 :(得分:7)

您始终可以编写 unconstrained 多态函数,该函数不需要任何类型类。一个简单的例子是

length :: [a] -> Int

–不需要类型类,并且(因为 )它可以用于任何类型 a。也就是说,length实际上并不关心该列表中的是什么,它仅关心其中包含这些值的结构。实际上,它永远不会对这些值做任何事情,而多态类型实际上可以保证这一点。

如果您需要的多态任务具有这种形式,即您实际上不需要访问的类型,那么您只知道它在那儿,那么您就不应编写/调用类型类,只需像length中那样使用ML风格的参数多态性。但是,很多时候 需要自己访问这些值,并以某种方式对其进行检查。在不限制您使用特定具体类型的情况下做到这一点,就是要使用什么类型类。正如您自己引用的,Eq是一个例子。

答案 1 :(得分:6)

  

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

,这是一种方式。但不是唯一的方法。例如,参数多态性只是意味着,如果您定义一个像init :: [a] -> [a]这样的函数,它将对任何a都有效。类型类用于 ad hoc多态性:根据类型,实现可能完全不同。这与参数多态性相反,在{em}中,head函数始终相同,而与a的类型无关。

  

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

,请参见上一节。

  

是否可以在不使用类型类==的情况下为/=(和任何其他类型)定义BoolEq

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

答案 2 :(得分:5)

在OOP和haskell中,多态功能之间存在差异,我之所以这样说是因为“多态”一词通常用于OOP中。

例如,列表上的功能是多态的:

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

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

在默认情况下,有一种方法可以快速实现类型类,例如EqShow,例如:

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

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

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

有所不同,因为现在a被限制了,它不能是任何“ a”。它应该实现类型类Show

最后,您可以看到,a函数中的cons类型比Show => a -> a函数中的mapShow类型更通用或更抽象。