
Yitzchak Gale wrote:
perhaps nowadays the type ought to be: concatMapM :: (Monad m, Traversable t) => (a -> m (t b)) -> t a -> m (t b)
apfelmus wrote:
I don't think that works in such generality since that would imply join :: Traversable t => t (t c) -> t c join = runIdentity . concatMapM return
Since return for the Identity monad is essential the identity, shouldn't we always have
mapM return = return
for that monad?
Yes, since mapM f = sequence . map f for all monads and sequence = id :: [Identity a] -> Identity [a] for the identity monad.
In that case, your formula is indeed always true:
runIdentity . concatMapM return = runIdentity . liftM join . mapM return = runIdentity . liftM join . return = runIdentity . return . join = join
Indeed, assuming that concatMapM f = liftM join . mapM f of course. What I wanted to say is that given the existence of a function concatMapM of the aforementioned type, you can construct a function of the type Traversable t => t (t a) -> t a which basically means (modulo laws) that every Traversable would have to be a monad. Since this is not always the case (really?), such a concatMapM that works for all Traversable t does not exist. Regards, apfelmus