Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generalizing "sequence" for all functors?

I have this code:

fmapM :: Monad m => (a -> m b) -> (t, a) -> m (t, b)
fmapM f (id, e) = do 
  ev <- f e
  return (id, ev)

which basically applies the function to the 2nd element in the tuple and then "extracts" the monad. Since the tuple is a functor, is there a way to generalize this for all functors? I cannot think of an implementation, but the type signature should be:

fmapM :: (Monad m, Functor f) => (a -> m b) -> f a -> m f b

it would seem like the 2nd step would be a "sequence" operation, which extracts the monad from another functor (the list). But sequence is not generalized to all functors. Can you come up with a generic implementation of fmapM?

Edit: I've realized that an old version of hugs did have this function implemented. However, I can't find the code. Now, it is suggested that I use foldable/traversable to achieve the same.

like image 526
BruceBerry Avatar asked Jul 10 '13 04:07

BruceBerry


1 Answers

The function you're looking for is traverse, from Data.Traversable:

traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

Note that you can't traverse any Functor -- for example, (r ->) -- so there's a separate subclass of Traversable functors. Also note that you don't need Monad -- just Applicative (this generalization is useful).

like image 141
shachaf Avatar answered Oct 16 '22 07:10

shachaf