4 ms·
I'm curious, what do you mean they compose better and allow for analysis [better than monads]?
by davdar 12y ago
I'm curious, what do you mean they compose better and allow for analysis [better than monads]?
- gergoerdi 12y agoYou can determine a lot more about a computation described only in terms of an applicative functor as you can from a monadic one, without running any of its effects (i.e. "statically"). It's easy to see why when you consider the opaqueness of the function in the right-hand side of a bind. Check out http://gergo.erdi.hu/blog/2012-12-01-static_analysis_with_applicatives/ http://gergo.erdi.hu/blog/2012-12-01-static_analysis_with_ap... for an example.
- tel 12y agogergoerdi covered analysis, but composition is simple. For any two Applicatives F and G and value type A the following 4 values are all Applicative values F A G A F (G A) G (F A) But for monads only the first two are monads for general monads F and G. So, Applicatives compose better!
- eru 12y agoAnd to get F (G A) with Monads, F needs to be a Monad transformer. In addition to composition, products of Applicatives are also Applicatives: (F A, G A)
- tel 12y agoEven for monad transformers it's not necessarily the case that direct composition leads to a monad. For instance, ContT looks like newtype ContT r m a = ContT ((a -> m r) -> m r) so ContT M A is not the same as Cont (M A). Monads also compose under products as two parallel monadic computations data (f * g) a = Pair (f a) (g a) p1 :: (f * g) a -> f a p1 (Pair fa _) = fa p2 :: (f * g) a -> g a p2 (Pair _ ga) = ga instance (Monad f, Monad g) => Monad (f * g) where return a = Pair (return a) (return a) Pair fa ga >>= k = Pair (fa >>= p1 . k) (ga >>= p2 . k) You can also talk about composition under sums data (f + g) a = Inl (f a) | Inr (g a) and you'll get compositions of applicatives here so long as you have a notion of natural transformation class Natural f g where phi :: f a -> g a instance (Applicative f, Applicative g, Natural f g) => Applicative (f + g) where pure a = Inl (pure a) Inl ff <*> Inl fa = Inl ( ff <*> fa) Inr gf <*> Inr ga = Inr ( gf <*> ga) Inl ff <*> Inr ga = Inr (phi ff <*> ga) Inr gf <*> Inl fa = Inr ( gf <*> phi fa) but there's no way to get a similar monad. It turns out that you have to "know what branch to go down before you start" in exactly the kind of way applicatives allow and monad preclude.