190 likes | 417 Views
重载与类型分类 Overloading and Type Classes. 什么是重载? 类型分类的概念 签名与特例. 重载. 运算符 (+) 可以用于计算两个相同类型数值之和: > 1 + 2 3 > 1.2 + 1.1 3.3 我们称运算符 (+) 被 重载 : (+) 可用于不同的类型,但是,它在不同类型上的定义不同。. 为什么使用重载. 假设我们要定义一个函数检查一个元素是否出现在一个布尔值列表中: elemBool :: Bool -> [Bool] -> Bool elemBool x [] = False
E N D
重载与类型分类Overloading and Type Classes • 什么是重载? • 类型分类的概念 • 签名与特例
重载 运算符(+) 可以用于计算两个相同类型数值之和: > 1 + 2 3 > 1.2 + 1.1 3.3 我们称运算符(+)被重载:(+)可用于不同的类型,但是,它在不同类型上的定义不同。
为什么使用重载 假设我们要定义一个函数检查一个元素是否出现在一个布尔值列表中: elemBool :: Bool -> [Bool] -> Bool elemBool x [] = False elemBool x (y:ys) = (x == y || elemBool x ys) 如果我们想定义一个函数检查一个元素是否出现在一个整数列表中: elemInt :: Int -> [Int] -> Bool 在这里重复上述定义,只是将布尔类型上的相等运算替换为整数类型上的相等即可。 Bool上的相等
为什么使用重载 在这种情况下,我们希望定义一个下列类型的函数: elem :: a -> [a] -> Bool elem x [] = False elem x (y:ys) = (x == y || elem x ys) 条件是类型a上定义了相等运算(==) 。 Haskell 使用类型分类系统实现上述需求。
类型分类Classes 一个类型分类或者类(class)是支持某些重载运算的类型的集合,这些运算又称为类的方法。 例如,定义了相等运算和不相等运算的类型的集合称为Eq(相等类),两个运算记作 (==) :: a -> a -> Bool (/=) :: a -> a -> Bool Eq类的定义是: class Eq a where (==) :: a - > a -> Bool (/=) :: a -> a -> Bool
定义类 class Visible a where toString :: a -> String size :: a -> Int 类名 签名:运算名及其类型
特例 一个类的成员称为一个特例。Eq的特例包括基本类型Int, Float, Bool, Char. 将一个类型定义为一个类的特例的方法是:通过使用instance 特例说明语句并定义类的方法。例如,说明Bool是Eq的特例: instance Eq Bool where True == True = True False == False = True _ == _ = False x /= y = not (x == y)
例 定义Bool是Visible的特例: instance Visible Bool where toString True = “True” toString False = “False” size _ = 1
函数elem 返回函数elem的例子,我们希望其类型是:elem :: a -> [a] -> Bool 其中类型a上定义了相等,或者说类型a是类Eq的特例。这样的要求可以在Haskell中如下说明: elem :: Eq a => a -> [a] -> Bool 函数的定义保持不变: elem x [] = False elem x (y:ys) = (x == y || elem x ys) 一个带有约束的类型称为重载类型,具有重载类型的函数称为重载函数。 约束
缺省定一 一个类的方法可以有缺省定义,缺省定义可以被特例定义覆盖。 例如,Eq类定义如下: class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y) 缺省定义
子类 一个类可能依赖于另一个类。例如,类Ord包含那些可以比较其值的类型。一个属于类Ord的类型不仅支持相等运算,而且支持比较运算>, >=等。为此,定义 class Eq a => Ord a where (<), (<=), (>), (>=) :: a -> a -> Bool max, min :: a -> a -> a compare :: a -> a -> Ordering Ord 是 Eq的子类
多重约束 在定义特例或者函数时可能需要多重约束。例如, instance (Eq a, Eq b) => Eq (a, b) where (x, y) == (u, v) = x == u && y == v instance (Visible a, Visible b) => Visible (a, b) where toString (x, y) = “(“++toString x ++ “,” ++ toString y ++ “)” size (x, y) = size x + size y
基本类 Equality: Eq class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y) 所有的基本类型都是Eq类的特例。列表类型,多元组类型都是Eq类的特例,只要其基类或者分量类型是Eq的特例。
可显示类 可显示类Show 包含其值可以显示成串的类型: class Show a where show :: a -> String 函数show将类型a的值显示成串。例如, instance Show Bool where show True = “True” show False = “False”
可读类 类Read 包含其值可以由串转换来的类型,它的方法是: read :: String -> a 所有的基本类型、列表类型和多元组类型都是类Read的特例,只要列表的基类或者多元组的分量类型属于类Read。 > read “False” :: Bool False > read “(‘a’, False)” :: (Char, Bool) (‘a’, False)
有序类 有序类Ord class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool min, max :: a -> a -> a 其中类型Ordering 包含三个元素LT, EQ 和GT, 分别表示比较两个值的三个可能结果。
缺省定义: compare x y | x == y = EQ | x <=y = LT | otherwise = GT x <= y = compare x y /= GT max x y | x >= y = x | otherwise = y
Num – 数值类 数值类Num包含其元素可以比较相等,可以显示并且支持下列数值元算的类型: (+) :: a -> a -> a (-) :: a -> a -> a (*) :: a -> a -> a negate :: a -> a abs :: a -> signum :: a -> a 基本类型Int, Integer 和Float 是 Num的特例.
多态函数与重载 函数length可以计算任意类型上列表的长度: length :: [a] -> Int 多态函数在所有类型上的定义是一致的。 而重载则不然,例如 elem :: Eq a => a -> [a] -> Bool 其定义依赖于不同的类型。 length [] = 0 length (x:xs) = 1 + length xs elem x [] = False elem x (y:ys) = (x == y||elem x ys)