Functor
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
(<$) = fmap . const
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<$>) = fmap
($>) :: Functor f => f a -> b -> f b
($>) = flip (<$)
void :: Functor f => f a -> f ()
void x = () <$ x
Functor(函子)是一个类型类,它是一种广义的能被映射的容器或计算环境。
将一个 a->b 的函数映射到一个 a 类型 的 Functor 之上会得到一个 b 类型的 Functor。
Functor的法则
fmap id ≡ id
fmap (f . g) ≡ fmap f . fmap g
[] 是 Functor
instance Functor [] where
-- fmap : (a -> b) -> [a] -> [b]
fmap = map
Prelude> :k []
[] :: * -> *
Prelude> fmap (+2) [1,2,3]
[3,4,5]
Prelude> (+2) <$> [1,2,3]
[3,4,5]
Prelude> 3 <$ [1,2,3]
[3,3,3]
Prelude Data.Functor> [1,2,3] $> 3
[3,3,3]
Prelude Data.Functor> void [1,2,3]
[(),(),()]
证明[]符合Functor法则:
1. fmap id ≡ id
fmap id [a] ≡ [id a] ≡ [a]
id [a] ≡ [a]
2. fmap (f . g) ≡ fmap f . fmap g
fmap (f . g) [a] ≡ [(f . g) a] ≡ [f (g a)]
(fmap f . fmap g) [a] ≡ fmap f (fmap g [a]) ≡ fmap f [g a] ≡ [f (g a)]
Maybe 是 Functor
instance Functor Maybe where
-- fmap : (a -> b) -> (Maybe a) -> (Maybe b)
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
Prelude> :k Maybe
Maybe :: * -> *
Prelude> fmap (+2) (Just 3)
Just 5
Prelude> (+2) <$> (Just 3)
Just 5
Prelude> fmap (+2) Nothing
Nothing
Prelude> 2 <$ Just 3
Just 2
证明Maybe符合Functor法则:
1. fmap id ≡ id
fmap id Nothing ≡ Nothing
id Nothing ≡ Nothing
fmap id (Just a) ≡ Just (id a) ≡ Just a
id (Just a) ≡ Just a
2. fmap (f . g) ≡ fmap f . fmap g
fmap (f . g) Nothing ≡ Nothing
(fmap f . fmap g) Nothing ≡ fmap f (fmap g Nothing) ≡ fmap f Nothing ≡ Nothing
fmap (f . g) (Just a) ≡ Just ((f . g) a) ≡ Just (f (g a))
(fmap f . fmap g) (Just a) ≡ fmap f (fmap g (Just a)) ≡ fmap f (Just (g a)) ≡ Just (f (g a))
((->) r) 是 Functor
instance Functor ((->) r) where
-- fmap : (a -> b) -> ((->) r a) -> ((->) r b)
-- fmap : (a -> b) -> (r -> a) -> (r -> b)
fmap = (.)
Prelude> fmap (+2) (*3) 4
14
Prelude> (+2) <$> (*3) $ 4
14
Prelude> 2 <$ (*3) $ 4
2
fmap (+2) (*3) 4 = 4*3+2 = 14
Either a 是 Functor
data Either a b = Left a | Right b
instance Functor (Either a) where
fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)
Prelude> :k (Either String)
(Either String) :: * -> *
Prelude> fmap (replicate 3) (Right "blah")
Right ["blah","blah","blah"]
Prelude> replicate 3 <$> Right "blah"
Right ["blah","blah","blah"]
Prelude> fmap (replicate 3) (Left "foo")
Left "foo"
Prelude> "hello" <$ Right "blah"
Right "hello"
Prelude> "hello" <$ Left "foo"
Left "foo"
((,) a) 是 Functor
instance Functor ((,) a) where
fmap f (x,y) = (x, f y)
Prelude> :k ((,)String)
((,)String) :: * -> *
Prelude> fmap (*3) (1,2)
(1,6)