Typeclassopedia presents Traversable:
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
sequenceA :: Applicative f => t (f a) -> f (t a)
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
sequence :: Monad m => t (m a) -> m (t a)
A good exercise is to figure out what the default implementations should be: given either traverse or sequenceA, how would you define the other three methods?
I came up with the following code that type-checks:
class (Functor t, Foldable t) => MyTraversable t where
traverse' :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse' = error "..."
sequenceA' :: Applicative f => t (f a) -> f (t a)
sequenceA' f = traverse' id f
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
mapM = traverse'
sequence' :: Monad m => t (m a) -> m (t a)
sequence' = sequenceA'
If my implementations of mapM and sequence' are correct, and, since every Monad is an Applicative:
λ: :i Monad
class Applicative m => Monad (m :: * -> *) where
...
then it's not clear to me why mapM and sequence' are even necessary. Why are they?
P.S. - Credit and my thanks to haoformayor for helping me out with sequenceA.
As mentioned in the comments, there was a time when not every Monad was an Applicative.
Just recently (in base-4.8 which shipped with GHC 7.10) the Applicative was made a superclass of Monad. You might have seen Applicative-Monad-Proposal, AMP.
Currently the Monad of no return, MRP (email-thread) is worked on, which will make
Monad's >> and Applicative's *> the same. Which eventlually would make possible to say that traverse = mapM and sequence = sequenceA. But that is a long process, which will take time.
So to answer your question: for history reasons.
Related
For example, MaybeT is defined as:
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a)}
But not:
newtype MaybeT m a =
MaybeT { runMaybeT :: Maybe (m a) }
Why is this?
After expanding newtypes, we have join :: Monad m => m (Maybe (m (Maybe a))) -> m (Maybe a) in the first case and join :: Monad m => Maybe (m (Maybe (m a))) -> Maybe (m a) in the second.
To implement the first join you need a way to distribute Maybe over m: dist1 :: Monad m => Maybe (m a) -> m (Maybe a) :
join1 :: m (Maybe (m (Maybe a))) -> m (Maybe a)
join1 = fmap join . join . fmap dist1
To implement the second join you need the opposite distributive law dist2 :: Monad m => m (Maybe a) -> Maybe (m a)
join2 :: Maybe (m (Maybe (m a))) -> Maybe (m a)
join2 = fmap join . join . fmap dist2
dist1 is easy to implement (I'll leave proving the monad transformer laws to you):
dist1 :: Monad m => Maybe (m a) -> m (Maybe a)
dist1 = sequenceA
dist2 is not so easy. It can't be done for an arbitrary Monad. As a counterexample, let's pick m to be the "reader" monad (->) r:
dist2 :: (r -> Maybe a) -> Maybe (r -> a)
Since you don't have access to an r, the only implementation of dist2 that'll typecheck is const Nothing, which clearly won't satisfy the monad laws.
Looking at StateT might be instructive:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
Here the state is neither "inner" nor "outer", but its type is interleaved with the monad it is transforming, some bits inside, some outside. And indeed
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
is all "outer". So it depends on what transformer it is. There's probably some category theory that at least partially explains this interleaving, I'm curious to know about it (intelligentsia?).
Contrast with applicative functors, for which
newtype Compose f g a = Compose { getCompose :: f (g a) }
is an applicative as well, so there is always a clear "inner/outer" relationship. You could make an applicative-only StateT, and finding its structure by Compose (State s):
ApplicativeStateT s f a = s -> (s, f a)
In fact, there's another one if you compose on the right:
ApplicativeStateT' s f a = f (s -> (s,a))
But monads have no such regularity.
Given:
sequence :: (Monad m, Traversable t) => t (m a) -> m (t a)
sequence_ :: (Monad m, Foldable t) => t (m a) -> m ()
Want:
sequenceMonoid :: (Monad m, Foldable t, Monoid t1) => t (m t1) -> m t1
sequenceMonoid = foldr (\m m' -> do { x <- m; xs <- m'; return (x `mappend` xs) }) (return mempty)
To be clear a list only version should be definable as:
sequenceMonoid :: (Monad m, Monoid t1) => [m t1] -> m t1
sequenceMonoid x = mconcat <$> (sequence x)
Example usage:
sequenceMonoid [Just [1,2],Just [3,4]]
Just [1,2,3,4]
Would this definition be correct? If it is I would have expected this to be a common pattern that already existed somewhere in the existing Monoid libraries?
This appears to be the most succinct way to write what you want (and also indicates why, as a trivial composition, it isn't included directly in the libs).
> :t fmap fold . sequence
fmap fold . sequence :: (Monad f, Traversable t, Monoid b) => t (f b) -> f b
You can generalize sequence to sequenceA to get something even slightly more general.
> :t fmap fold . sequenceA
fmap fold . sequenceA :: (Applicative f, Traversable t, Monoid b) => t (f b) -> f b
I recently stumbled across Djinn and was briefly playing around with it to try to see whether it would be useful in my everyday coding workflow. I was excited to see that Djinn had monads and tried to see whether it might be able to find some cool functions.
Djinn did in fact work some wonders. The type signature of the initially (at least to me) unintuitive function >>= (>>=) is Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b. Djinn was able to immediately demystify this by stating
Djinn> f ? Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b
f :: (Monad m) => ((a -> m b) -> m a) -> (a -> m b) -> m b
f a b = a b >>= b
Unfortunately, Djinn can't seem to find other standard functions on monads, despite knowing about the Monad typeclass.
join (which should be join = (>>= id) or in Djinn's more verbose syntax join a = a >>= (\x -> x))
Djinn> join ? Monad m => m (m a) -> m a
-- join cannot be realized.
liftM (which should be liftM f = (>>= (return . f)) or in Djinn's more verbose syntax liftM a b = b >>= (\x -> return (a x)))
Djinn> liftM ? Monad m => (a -> b) -> m a -> m b
-- liftM cannot be realized.
Even the basic return :: Monad m => m a -> m (m a) cannot be found by Djinn or return :: Monad m => (a, b) -> m (a, b).
Djinn> f ? Monad m => (a, b) -> m (a, b)
-- f cannot be realized.
Djinn knows how to use \ to construct anonymous functions so why is this the case?
My rough suspicion is that perhaps Djinn has a simplistic notion of typeclass and somehow treats m a as "fixed" so that m (a, b) is not seen as a case of m a, but I have no idea how to make that any more concrete than its current hand-wavy form or whether that intuition is correct.
Supporting type classes properly looks a lot like supporting rank-2 types; compare:
join :: Monad m
=> m (m a) -> m a
vs:
join :: (forall a. a -> m a)
-> (forall a b. m a -> (a -> m b) -> m b)
-> m (m a) -> m a
Unfortunately, the techniques Djinn uses don't handle rank-2 types at all. If you float the foralls so that Djinn can process it, suddenly what you get instead are concrete choices:
join :: (b -> m b)
-> (m c -> (c -> m d) -> m d)
-> m (m a) -> m a
which looks a lot less like you could implement it! If you tell Djinn which instantiations to use, it does a lot better, of course.
join :: (b -> m b)
-> (m (m a) -> (m a -> m a) -> m a)
-> m (m a) -> m a
For this one, Djinn will give the right implementation. ...but then, that's cheating.
This question has been asked before, but without a real answer. In fact the accepted answer suggests that it is not possible, despite the fact that
StateT is a Monad, and hence a superset of Applicative. As a result, the standard libraries simply use (<*>) = ap
(as Petr notes) composing applicatives always yields an applicative.
One of the implementations of MaybeT I've read about used
liftA2 (<*>) :: (Applicative f, Applicative f1) => f (f1 (a -> b)) -> f (f1 a) -> f (f1 b)
to implement Applicative but I can't make that work here. My work in progress has tried lots of options around the following:
-- (<*>) :: StateT s f (a -> b) -> State s f a -> State s f b
instance (Applicative f) => Applicative (StateT s f) where
pure a = StateT $ \s -> pure (a, s)
(StateT f) <*> (StateT g) = StateT $ \s -> -- f :: s -> m (a -> b, s), g :: s -> m (a, s)
let
mabs = f s -- mabs :: m (a -> b, s)
mab = fmap fst mabs
ms' = fmap snd mabs
in undefined
I'm wondering what I am missing, and hoping that I will learn something about Applicative in the process.
Tony uses some alternative notation, and Simon's answer is very terse, so here is what I ended up with:
-- (<*>) :: StateT s f (a -> b) -> State s f a -> State s f b
instance (Monad f, Applicative f) => Applicative (StateT s f) where
pure a = StateT $ \s -> pure (a, s)
StateT f <*> StateT a =
StateT $ \s ->
f s >>= \(g, t) -> -- (f s) :: m (a->b, s)
let mapper = \(z, u) -> (g z, u) -- :: (a, s) -> (b, s)
in fmap mapper (a t) -- (a t) :: m (a, s)
I had to declare f also a Monad, but that is OK as it is part of the definition of a Monad transformer, as I understand it.
An implementation (taken from Tony Morris' functional programming course) could be
(<*>) :: (Functor f, Monad f) =>
StateT s f (a -> b)
-> StateT s f a
-> StateT s f b
StateT f <*> StateT a =
StateT (\s -> (\(g, t) -> (\(z, u) -> (g z, u)) <$> a t) =<< f s)
When use Data.Traversable I frequently requires some code like
import Control.Applicative (Applicative,(<*>),pure)
import Data.Traversable (Traversable,traverse,sequenceA)
import Control.Monad.State (state,runState)
traverseF :: Traversable t => ((a,s) -> (b,s)) -> (t a, s) -> (t b, s)
traverseF f (t,s) = runState (traverse (state.curry f) t) s
to traverse the structure and build up a new one driven by some state. And I notice the type signature pattern and believe it could be able to generalized as
fmapInner :: (Applicative f,Traversable t) => (f a -> f b) -> f (t a) -> f (t b)
fmapInner f t = ???
But I fail to implement this with just traverse, sequenceA, fmap, <*> and pure. Maybe I need stronger type class constrain? Do I absolutely need a Monad here?
UPDATE
Specifically, I want to know if I can define fmapInner for a f that work for any Traversable t and some laws for intuition applied (I don't know what the laws should be yet), is it imply that the f thing is a Monad? Since, for Monads the implementation is trivial:
--Monad m implies Applicative m but we still
-- have to say it unless we use mapM instead
fmapInner :: (Monad m,Traversable t) => (m a -> m b) -> m (t a) -> m (t b)
fmapInner f t = t >>= Data.Traversable.mapM (\a -> f (return a))
UPDATE
Thanks for the excellent answer. I have found that my traverseF is just
import Data.Traversable (mapAccumL)
traverseF1 :: Traversable t => ((a, b) -> (a, c)) -> (a, t b) -> (a, t c)
traverseF1 =uncurry.mapAccumL.curry
without using Monad.State explicitly and have all pairs flipped. Previously I though it was mapAccumR but it is actually mapAccumL that works like traverseF.
I've now convinced myself that this is impossible. Here's why,
tF ::(Applicative f, Traversable t) => (f a -> f b) -> f (t a) -> f (t b)
So we have this side-effecting computation that returns t a and we want to use this to determine what side effects happen. In other words, the value of type t a will determine what side effects happen when we apply traverse.
However this isn't possible possible with the applicative type class. We can dynamically choose values, but the side effects of out computations are static. To see what I mean,
pure :: a -> f a -- No side effects
(<*>) :: f (a -> b) -> f a -> f b -- The side effects of `f a` can't
-- decide based on `f (a -> b)`.
Now there are two conceivable ways to determine side effects at depending on previous values,
smash :: f (f a) -> f a
Because then we can simply do
smash $ (f :: a -> f a) <$> (fa :: f a) :: f a
Now your function becomes
traverseF f t = smash $ traverse (f . pure) <$> t
Or we can have
bind :: m a -> (a -> m b) -> m b -- and it's obvious how `a -> m b`
-- can choose side effects.
and
traverseF f t = bind t (traverse $ f . pure)
But these are join and >>= respectively and are members of the Monad typeclass. So yes, you need a monad. :(
Also, a nice, pointfree implementation of your function with monad constraints is
traverseM = (=<<) . mapM . (.return)
Edit,
I suppose it's worth noting that
traverseF :: (Applicative f,Traversable t) => (f a -> f b) -> t a -> f (t a)
traverseF = traverse . (.pure)