Haskell中的类型类和多态性
Haskell是一种纯函数式编程语言,其类型系统非常强大。在Haskell中,类型类和多态性是两个非常重要的概念。
类型类用于定义一组相关类型的通用行为。它类似于面向对象编程中的接口或者Java中的泛型。通过使用类型类,我们可以定义一些通用的函数或者操作符,并使这些函数或操作符能够用于多种类型。
比如,考虑下面这个例子,我们定义了一个类型类Showable,它包含一个函数show,这个函数接受一个参数并返回一个字符串表示该参数的内容。
class Showable a where show :: a -> String
然后我们可以为一些类型实现Showable类型类:
instance Showable Int where show = show instance Showable Bool where show True = "True" show False = "False"
接着,我们可以定义一个通用的函数printShowable,它接受一个实现了Showable类型类的参数,并将其内容打印出来:
printShowable :: Showable a => a -> IO () printShowable x = putStrLn (show x)
通过这样定义,我们可以对任意实现了Showable的类型使用printShowable函数:
main :: IO () main = do printShowable (3 :: Int) -- 输出 3 printShowable True -- 输出 True
这里的:: Int用于明确指定3的类型为Int,因为Haskell推断出的默认类型为Integer。
多态性则是指函数或者操作符可以用于多种类型的参数。在Haskell中,有两种形式的多态性:parametric polymorphism和ad-hoc polymorphism。
parametric polymorphism是指函数或者操作符可以适用于任意类型的参数。比如,考虑下面这个函数length,它返回一个列表的长度:
length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs main :: IO () main = do print (length [1, 2, 3]) -- 输出 3 print (length ["hello", "world"]) -- 输出 2
这里的a是一个类型变量,可以表示任意类型。因此,length函数可以适用于任意类型的列表。
ad-hoc polymorphism是指函数或者操作符在不同类型参数上有不同的行为。这通过类型类来实现。我们在之前的例子中已经见过了Showable这个类型类的例子。
class Eq a where (==) :: a -> a -> Bool instance Eq Int where (==) = (==) instance Eq Bool where (==) = (==) main :: IO () main = do print (3 == 3) -- 输出 True print (True == False) -- 输出 False
这里我们定义了一个类型类Eq,它包含一个函数==,这个函数接受两个参数并返回一个布尔值。然后我们为Int和Bool类型实现了Eq类型类,分别使用了==操作符的实现。
通过这样定义,我们可以对任意实现了Eq的类型使用==操作符。
