美文网首页Haskell
[Haskell] Applicative

[Haskell] Applicative

作者: 何幻 | 来源:发表于2016-03-04 07:15 被阅读97次
    class (Functor f) = Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b
    

    其中f并不是一个具体类型,而是一个单参类型构造器(:k f = * -> *)。f还必须首先是一个Functor。
    类型f a的值称为applicative value。
    <u></u>pure接受普通类型的值,返回包含这个普通类型值的applicative value。
    <u></u><*>接受一个包含映射的applicative value,返回一个applicative value上的映射。

    Applicative Law
    (1)pure id <*> v = v
    (2)pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
    (3)pure f <*> pure x = pure (f x)
    (4)u <*> pure y = pure ($ y) <*> u

    Examples

    (1)Maybe是Applicative类型类的实例

    instance Applicative Maybe where
    pure = Just
    Nothing <*> _ = Nothing
    (Just f) <*> somthing = fmap f something
    

    我们看一下<*>是如何实例化的

    (<*>) :: f (a -> b) -> f a -> f b
    = Maybe (a -> b) -> Maybe a -> Maybe b
    
    ghci> Just (+ 3) <*> Just 9
    Just 12
    
    ghci> pure (+) <*> Just 3 <*> Just 5
    Just 8
    

    注:
    其中“<*>”是左结合的。

    pure (+) <*> Just 3 <*> Just 5
    = (pure (+) <*> Just 3) <*> Just 5
    = (Just (+) <*> Just 3) <*> Just 5
    = Just (3 +) <*> Just 5
    = Just 8
    

    所以,如果g是一个多参普通函数,xy...是包含普通值的applicative value,则
    <u></u>pure g <*> x <*> y <*> ... 返回一个applicative value,它包含的值是,g作用于xy...包含的值的结果。

    另外,我们看到,pure g <*> x = fmap g x
    所以,pure g <*> x <*> y <*> ... = fmap g x <*> y <*> ...

    我们定义:

    (<$>) :: (Functor f) => (a -> b) -> f a -> f b
    f <$> x = fmap f x
    

    因此,pure (+) <*> Just 3 <*> Just 5 = (+) <$> Just 3 <*> Just 5

    (2)[]是Applicative类型类的实例

    instance Applicative [] where
    pure x = [x]
    fs <*> xs = [f x | f <- fs, x <- xs]
    

    我们看一下<*>是如何实例化的

    (<*>) :: f (a -> b) -> f a -> f b
    = [a -> b] -> [a] -> [b]
    
    ghci> [(* 0), (+ 100), (^2)] <*> [1, 2, 3]
    [0, 0, 0, 101, 102, 103, 1, 4, 9]
    
    ghci> [(+), (*)] <*> [1, 2] <*> [3, 4]
    [4, 5, 5, 6, 3, 4, 6, 8]
    

    其中,

    [(+), (*)] <*> [1, 2] <*> [3, 4]
    = ([(+), (*)] <*> [1, 2]) <*> [3, 4]
    = [(1 +), (2 +), (1 *), (2 *)] <*> [3, 4]
    = [4, 5, 5, 6, 3, 4, 6, 8]
    

    (3)IO是Applicative类型类的实例

    instance Applicative IO where
    pure = return
    a <*> b = do
        f <- a
        x <- b
        return (f x)
    

    我们看一下<*>是如何实例化的

    (<*>) :: f (a -> b) -> f a -> f b
    = IO (a -> b) -> IO a -> IO b
    

    注:
    (1)IO也是一个单参类型构造器(:k IO = * -> *)。
    (2)IO String类型表示输出StringIO ()类型表示不输出。
    (3)()是一个空tuple类型,这个类型只有一个值,即()
    所以,()在不同的上下文中,既可以表示类型,也可以表示值。

    (++) <$> getLine <*> getLine
    = do
    a <- getLine
    b <- getLine
    return $ a ++ b
    

    其中getLine :: IO String

    (4)(->) r是Applicative类型类的实例

    instance Applicative ((->) r) where
    pure x = \_ -> x
    f <*> g = \x -> f x (g x)
    

    我们看一下pure<*>是如何实例化的

    pure :: a -> f a
    = a -> ((-> r) a)
    = a -> (r -> a)
    
    (<*>) :: f (a -> b) -> f a -> f b
    = ((->) r (a -> b)) -> ((->) r a) -> ((->) r b)
    = (r -> a -> b) -> (r -> a) -> (r -> b)
    
    ghci> (+) <$> (+ 3) <*> (* 100) $ 5
    508
    
    pure (+) <*> (+ 3)
    = \_ -> (+) <*> (+ 3)
    = \x -> (+) ((+ 3) x)
    = \x -> ((x + 3) +)
    
    pure (+) <*> (+ 3) <*> (* 100)
    = \y -> ((y + 3) +) <*> (* 100)
    = \x -> ((x + 3) +) (x * 100)
    = \x -> (x + 3) + (x * 100)
    

    相关文章

      网友评论

        本文标题:[Haskell] Applicative

        本文链接:https://www.haomeiwen.com/subject/veunkttx.html