Proving Composition Law for Maybe Applicative

前端 未结 4 1815
旧巷少年郎
旧巷少年郎 2021-01-12 21:19

So, I wanted to manually prove the Composition law for Maybe applicative which is:

u <*> (v <*> w) = pure (.) <*> u <*> v <*> w         


        
4条回答
  •  -上瘾入骨i
    2021-01-12 21:40

    You translated the use of (<*>) through fmap. The other answers also do some pattern matching.

    Usually you need to open the definition of the functions to reason about them, not just assume what they do. (You assume (pure f) <*> x is the same as fmap f x)

    For example, (<*>) is defined as ap for Maybe in Control.Applicative (or can be proven to be equivalent to it for any Monad, even if you redefine it), and ap is borrowed from Monad, which is defined as liftM2 id, and liftM2 is defined like so:

    liftM2 f m1 m2 = do
        x <- m1
        y <- m2
        return $ f x y
    

    So, reduce both left- and right-hand sides to see they are equivalent:

    u <*> (v <*> w) = liftM2 id u (liftM2 id v w)
     = do
         u1 <- u
         v1 <- do
                 v1 <- v
                 w1 <- w
                 return $ id v1 w1
         return $ id u1 v1
     = do
         u1 <- u
         v1 <- do
                 v1 <- v
                 w1 <- w
                 return $ v1 w1
         return $ u1 v1
     -- associativity law: (see [1])
     = do
         u1 <- u
         v1 <- v
         w1 <- w
         x <- return $ v1 w1
         return $ u1 x
     -- right identity: x' <- return x; f x'  == f x
     = do
         u1 <- u
         v1 <- v
         w1 <- w
         return $ u1 $ v1 w1
    

    Now, the right-hand side:

    pure (.) <*> u <*> v <*> w
     = liftM2 id (liftM2 id (liftM2 id (pure (.)) u) v) w
     = do
         g <- do
                f <- do
                       p <- pure (.)
                       u1 <- u
                       return $ id p u1
                v1 <- v
                return $ id f v1
         w1 <- w
         return $ id g w1
     = do
         g <- do
                f <- do
                       p <- return (.)
                       u1 <- u
                       return $ p u1
                v1 <- v
                return $ f v1
         w1 <- w
         return $ g w1
     -- associativity law:
     = do
        p <- return (.)
        u1 <- u
        f <- return $ p u1
        v1 <- v
        g <- return $ f v1
        w1 <- w
        return $ g w1
     -- right identity: x' <- return x; f x'  ==  f x
     = do
        u1 <- u
        v1 <- v
        w1 <- w
        return $ ((.) u1 v1) w1
     -- (f . g) x  == f (g x)
     = do
        u1 <- u
        v1 <- v
        w1 <- w
        return $ u1 $ v1 w1
    

    That's it.

    [1] http://www.haskell.org/haskellwiki/Monad_laws

提交回复
热议问题