class Functor f where
fmap :: (a -> b) -> f a -> f b
其中f并不是一個(gè)具體類型,而是一個(gè)單參類型構(gòu)造器(:k f = * -> *)。
類型f a的值稱為functor value。
<u></u>fmap接受一個(gè)普通函數(shù)a -> b,返回一個(gè)functor value上的函數(shù)f a -> f b。
Functor Law
只是Functor類型類的實(shí)例,還不是一個(gè)數(shù)學(xué)意義上的Functor,需要滿足以下定律。
(1)fmap id = id
(2)fmap (f . g) = fmap f . fmap g
Examples
(1)[]是Functor類型類的實(shí)例
instance Functor [] where
fmap = map
列表類型上的map就是fmap。
map :: (a -> b) -> [a] -> [b]
注:
不能寫“instance Functor [a] where”而要寫“[]” (:k [] = * -> *),因?yàn)镕unctor類型類的實(shí)例必須是一個(gè)單參類型構(gòu)造器,而“[a]”是一個(gè)具體類型。
(2)Maybe是Functor類型類的實(shí)例
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
其中,Maybe類型的定義如下:
data Maybe a = Just a | Nothing
其中,fmap :: (a -> b) -> Maybe a -> Maybe b
(3)Tree是Functor類型類的實(shí)例
instance Functor Tree where
fmap f EmptyTree = EmptyTree
fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right)
其中,Tree類型的定義如下:
data Tree a = EmptyTree | Node a (Tree a) (Tree a)
(4)Either a是Functor類型類的實(shí)例
<u></u>Either a b是一個(gè)具體類型,而Functor類型類的實(shí)例必須是單參類型構(gòu)造器。
而Either是接受兩個(gè)參數(shù)的類型構(gòu)造器(:k Either = * -> * -> *),也不可以。
部分應(yīng)用Either的一個(gè)參數(shù)類型,得到Either a,它是一個(gè)單參類型構(gòu)造器了(:k Either a = * -> *)。
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
其中,Either類型的定義如下:
data Either a b = Left a | Right b
(5)(->) r是Functor類型類的實(shí)例
函數(shù)類型r -> a可以改寫為:(->) r a,則“->”就是一個(gè)接受兩個(gè)參數(shù)的類型構(gòu)造器了(:k (->) = * -> * -> *)。
如果已提供一個(gè)類型參數(shù),則“(->) r”就是單參類型構(gòu)造器了(:k (-> r) = * -> *),可以作為Functor類型類的實(shí)例了。其中,(->) r = (r ->)
instance Functor ((->) r) where
fmap f g = (\x -> f (g x))
我們考慮一下fmap的類型是如何實(shí)例化的
fmap :: (a -> b) -> f a -> f b
= (a -> b) -> ((->) r a) -> ((->) r b)
= (a -> b) -> (r -> a) -> (r -> b)
而這正好是函數(shù)復(fù)合“.”的類型,所以fmap還可以定義為:
instance Functor ((->) r) where
fmap = (.)
因此,fmap作用在兩個(gè)函數(shù)上面,就相當(dāng)于進(jìn)行函數(shù)復(fù)合。
ghci> fmap (* 3) (+ 100) 1
303
還可以有不同的寫法:
fmap (* 3) (+ 100) 1
= (* 3) `fmap` (+ 100) $ 1
= (* 3) . (+ 100) $ 1