Home > front end >  Is there a way to commute monads automatically?
Is there a way to commute monads automatically?

Time:04-29

I have written a program to pull a Maybe out of a pair:

deMaybe :: (a, Maybe b) -> Maybe (a, b)
deMaybe (_, Nothing) = Nothing
deMaybe (x,Just y) = Just (x, y)

I know that Maybe is a monad and (,) a is a functor (among other typeclasses). I'm wondering if there is a higher-level function I'm missing, such as:

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

My question is: can I write deMaybe with a more general type signature like that of the hypothetical commute, acknowledging that I am trying to commute one functor past another? Can this be done using functions such as fmap, >>=, pure, &c.?

CodePudding user response:

You can work with sequence :: (Traversable t, Monad m) => t (m a) -> m (t a), but this requires a Traversable. For t ~ (b, ) and m ~ Maybe, this thus works as:

Prelude> sequence (2, Just 3)
Just (2,3)
Prelude> sequence (2, Nothing)
Nothing

A Traversable is a typeclass for data structures that can be transformed to an item with the same shape. We need this to construct thus a 2-tuple (or list, or something similar).

or we can use sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) as @chepner says, which is more general since all Monads are also Applicatives:

Prelude> sequenceA (2, Just 3)
Just (2,3)
Prelude> sequenceA (2, Nothing)
Nothing
  • Related