Applicative
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
(*>) :: f a -> f b -> f b
a1 *> a2 = (id <$ a1) <*> a2
(<*) :: f a -> f b -> f a
(<*) = liftA2 const
Applicative(应用函子) 是一个类型类。Functor 是 Applicative 的基类。
pure 函数将值放入 Applicative 这个计算环境之中。
<*> (apply)操作符将封装在 Applicative 中的函数应用到封装在 Applicative 中的值之上。
lift2 函数提升一个二元函数,将其应用到两个封装在 Applicative 中的值之上。
pure 函数将值放入 Applicative 这个计算环境之中。
<*> (apply)操作符将封装在 Applicative 中的函数应用到封装在 Applicative 中的值之上。
lift2 函数提升一个二元函数,将其应用到两个封装在 Applicative 中的值之上。
Applicative的法则
pure id <*> v = v
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u
<$>
(<$>) :: Functor f => (a -> b) -> f a -> f b
[] 是 Applicative
instance Applicative [] where
pure x = [x]
-- (<*>) :: [a -> b] -> [a] -> [b]
fs <*> xs = [f x | f <- fs, x <- xs]
Prelude> [(*0),(+100),(^2)] <*> [1,2,3]
[0,0,0,101,102,103,1,4,9]
Prelude> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
[8.0,10.0,2.5]
Maybe 是 Applicative
instance Applicative Maybe where
pure = Just
-- (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
Just f <*> m = fmap f m
Nothing <*> _m = Nothing
Prelude> Just (+2) <*> Just 3
Just 5
Prelude> (+) <$> Just 2 <*> Just 3
Just 5
Prelude> Just (+2) <*> Nothing
Nothing
Prelude> Just 7 <* Just 8
Just 7
Prelude> Just 7 *> Just 8
Just 8
Prelude> liftA2 (:) (Just 3) (Just [4])
Just [3,4]
((->) r) 是 Applicative
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
Prelude> (+) <$> (+2) <*> (*3) $ 4
18
(+) <$> (+2) <*> (*3) $ 4 = (4+2)+(4*3) = 18
ZipList 是 Applicative
newtype ZipList a = ZipList { getZipList :: [a] }
instance Applicative ZipList where
pure x = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)
Prelude Control.Applicative> getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]
[101,102,103]
(<**>), liftA, liftA3
(<**>) :: Applicative f => f a -> f (a -> b) -> f b
(<**>) = liftA2 (\a f -> f a)
liftA :: Applicative f => (a -> b) -> f a -> f b
liftA f a = pure f <*> a
liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 f a b c = liftA2 f a b <*> c
Prelude Control.Applicative> Just 2 <**> Just (*3)
Just 6
Prelude Control.Applicative> liftA (+2) (Just 3)
Just 5
Prelude Control.Applicative> liftA3 (,,) (Just 3) (Just 4) (Just 5)
Just (3,4,5)