类型类#
声明#
class <typeClass> <typeVariable> where
<functionDeclaration>
...
类型类:约束类型的接口,同一类型类下的类型具有相同行为、能使用该类型类下所定义的方法;
class Eq a where (==) :: a -> a -> Bool -- 任何属于 'Eq' 类型类的成员 (/=) :: a -> a -> Bool -- 都可使用这两个函数
语法格式:
class
关键字定义一个类型类;- 类型类名称需大写字母开头;
- 类型变量表示该类型类的成员,使用小写字母;
where
关键字定义类型类体;- 类型类体即一系列函数声明,不需要定义函数体;
deriving
关键字可自动将数据类型转换为类型类的实例,使得该数据类型能使用类型类下定义的方法;
1-- | 命令式语言类似的布尔值:
2-- 非空为 'False',否则为 'True'。
3-- 'YesNo' 类型类的实例成员都能使用该类型类下定义的函数。
4class YesNo a where
5 yesno :: a -> Bool
6
7-- | '0' 为 'False',否则为 'True'。
8instance YesNo Int where
9 yesno 0 = False
10 yesno _ = True
11
12-- | 空列表为 'False',否则为 'True'。
13instance YesNo [a] where
14 yesno [] = False
15 yesno _ = True
16
17-- | 'id' 函数按原样返回接受到的值。
18instance YesNo Bool where
19 yesno = id
20
21exp1 = yesno (0 :: Int) -- False
22exp2 = yesno "" -- False
23exp3 = yesno [] -- False
24exp4 = yesno "alice" -- True
实例#
instance <typeClass> <type> where
<functionBodies>
...
- 类型类的实例享用类型类定义的方法;
- 语法格式:
instance
关键字定义类型类实例;- 类型类为被派生的类型类;
- 类型指定该类型为类型类实例/成员;
where
关键字定义实例体;- 实例体即一系列函数体,指定该类型该如何执行函数;
- 部分应用:类型类的实质也是函数,经过柯里化,因此可以接受少于形参数量的实参,实现部分应用;
- 类型类实例支持模式匹配;
1data TrafficLight = Red | Yellow | Green
2
3instance Show TrafficLight where
4 show Red = "Red light"
5 show Yellow = "Yellow light"
6 show Green = "Green light"
7
8instance Eq TrafficLight where
9 Red == Red = True
10 Yellow == Yellow = True
11 Green == Green = True
12 _ == _ = False
13
14exp1 = Red -- Red light
15exp2 = Green -- Yellow light
16exp3 = Red == Green -- False
17exp4 = Red `elem` [Red, Yellow, Green] -- True
类型约束#
instance (<typeClass> <typeVariable>, ...) => <type> where
- 类型类支持类型约束语法,意义相似;
1infixr 5 :^:
2data Tree a = Leaf a | Tree a :^: Tree a
3 deriving (Show, Read)
4
5-- | 'a' 是 'Eq' 的成员,同时也是 'Tree' 的成员。
6-- 同时,'Tree' 本身也属于 'Eq'。
7instance Eq a => Eq (Tree a) where
8 Leaf a == Leaf b = a == b
9 m :^: n == x :^: y = m == x && n == y
10 _ == _ = False
11
12-- | 同上。
13instance Ord a => Ord (Tree a) where
14 Leaf a <= Leaf b = a <= b
15 Leaf a <= m :^: n = True
16 m :^: n <= Leaf a = False
17 m :^: n <= x :^: y = m < x || m == x && n <= y
18
19exp1 = Leaf 1 :^: Leaf 2 :^: Leaf 3
20 -- Leaf 1 :^: (Leaf 2 :^: Leaf 3)
21exp2 = Leaf 1 :^: Leaf 2 <= Leaf 1 :^: Leaf 3 -- True
22exp3 = Leaf 5 <= Leaf 2 :^: Leaf 3 -- True
种类#
<type> :: <kind>
种类:类型构造器的类型;
GHCi 中使用
:kind
命令可查看类型构造器的种类;语法格式:
*
:该类型为具体类型,不接受类型参数;Int :: * -- 'Int' 为具体类型 Maybe Int :: * -- 'Maybe Int' 同上
P -> Q
:接受一个类型P
,返回一个类型Q
;Maybe :: * -> * -- 接受一个具体类型(Int) -- 并返回具体类型(Maybe Int) Either :: * -> * -> * -- 接受两个 Either String :: * -> * -- 部分应用 (->) :: * -> * -> *