我试图弄清类型类的目的,如果不使用类型类,还有什么呢?
类型类是定义多态函数的一种方法吗?
类型类是定义多态函数的唯一方法吗?例如:
class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) instance Eq Bool where False == False = True True == True = True _ == _ = False
我可以定义==
和/=
对Bool
(以及任何其他类型),而无需使用类型的类Eq
?
在有其他方法的地方,何时应该使用类型类或其他方法来定义多态函数?
您始终可以编写无约束的多态函数,该函数不需要任何类型类。一个简单的例子是
length :: [a] -> Int
–这不需要类型类,并且(因为)它适用于任何类型 a
。也就是说,length
实际上并不在乎该列表中的值是什么,它仅在乎包含这些值的结构。实际上,它永远不会对这些值本身做任何事情,而多态类型实际上可以保证这一点。
如果您需要的多态任务是这种形式的,即实际上不需要访问的类型,而您只知道它在那里,那么您就不应该编写/调用类型类,只需使用ML样式的参数多态性即可,如length
。但是,很多时候您将需要访问值本身,以某种方式对其进行检查。在不限制您使用特定具体类型的情况下做到这一点,就是要使用什么类型类。Eq
如您所言,就是一个例子。
类型类是定义多态函数的一种方法吗?
是的,这是一种方法。但不是唯一的方法。例如,参数多态性只是意味着,如果您定义类似的函数init :: [a] -> [a]
,它将对任何函数都有效a
。类型类用于临时多态性:根据类型,实现可以完全不同。这与参数多态性相反,在参数多态性中,head
函数始终是相同的,而与的类型无关a
。
类型类是定义多态函数的唯一方法吗?
不,请参见上一节。
我可以定义
==
和/=
对Bool
(以及任何其他类型),而无需使用类型的类Eq
?
这取决于所有类型的实现是否相同。您可以使用该-XNoImplicitPrelude
标志来避免导入Prelude
,然后可以定义自己的(==)
函数。
OOP和haskell中的多态功能之间存在差异,我之所以这样说是因为OOP中通常使用术语“多态”。
例如,列表中的函数是多态的:
cons:: a -> [a] -> [a] cons x xs = x:xs
其中a是多态类型,那里没有类型类。
顺便说一句,默认情况下有一种方法可以快速实现类型类,例如Eq
或Show
,例如:
data MBool = MTrue | MFalse deriving (Eq, Show)
因此,区别在于类型类是一个约束,想象一下这个函数与列表:
mapShow :: Show a => [a] -> [String] mapShow = map show
这是不同的,因为现在a被限制了,它不能是任何“ a”。它应该实现typeclass Show
。
总之,您可以看到函数a
类型cons
比函数Show => a -> a
类型更通用或更抽象mapShow
。