Applicative functor expressions are simply functional applications in the context of a functor. Hence:
pure f <*> pure a <*> pure b <*> pure c -- is the same as: pure (fabc)
We want to prove that:
pure (.) <*> u <*> v <*> w == u <*> (v <*> w)
Consider:
u = pure f v = pure g w = pure x
Therefore, the left side:
pure (.) <*> u <*> v <*> w pure (.) <*> pure f <*> pure g <*> pure x pure ((.) fgx) pure ((f . g) x) pure (f (gx)) pure f <*> pure (gx) pure f <*> (pure g <*> pure x) u <*> (v <*> w)
For Maybe we know that pure = Just . Therefore, if u , v and w are Just values, then we know that the law of composition holds.
However, what if any of them are Nothing ? We know that:
Nothing <*> _ = Nothing _ <*> Nothing = Nothing
Therefore, if any of them is Nothing , then the whole expression becomes Nothing (except for the second case, if the first argument is undefined ), and since the Nothing == Nothing law still holds.
Finally, what about undefined (aka bottom) values? We know that:
(Just f) <*> (Just x) = Just (fx)
Therefore, the following expressions will stop the program:
(Just f) <*> undefined undefined <*> (Just x) undefined <*> Nothing
However, the following expression will result in Nothing :
Nothing <*> undefined
In any case, the law of composition is maintained.