Suppose I have a value of type Monad m => (m a, m a), and I want to "sequence" the pair to create a value of type Monad m => m (a, a) that combines the monadic context of the two values in the same way the "sequence" function does. Is there some standard function or standard way of doing this? And does this operation even make sense?
6
votes
3 Answers
10
votes
8
votes
There wouldn't be a single function for all the different tuple types, since it wouldn't have a single type.
You could define a family of functions like:
ts0 = return
ts2 = uncurry $ liftM2 (,)
ts3 = uncurr3 $ liftM3 (,,)
{- ... -}
uncurr3 f (x, y, z) = f x y z
Of course, sequence in general is better applied to applicatives instead of monads, which is why it is part of the Traversable typeclass. It would be possible to make homogenous tuples [(a,a,a) but not (a,b,a)] an instance of MonoTraversable, I believe.
You should also see another answer which indicates there is already a library containing this family of functions.
7
votes
`some code`. Also, it's much easier if you use the;to separate definitions:sequence' (ma, mb) = (x, y) where x=head L; y= last L; L = sequence [ma, mb]- Bakuriuuncurry $ liftM2 (,) :: Monad m => (m a1, m a2) -> m (a1, a2)You can also do it with applicatives. I wonder if there are mono-traversable instances for homogenous tuples up to some size. - Boyd Stephen Smith Jr.Applicative, and it'd be something like(<,>) :: Applicative f -> f a -> f b -> f (a, b). This function is not a standard one, but you often find people talking about it because the associativity law thatApplicativeinstances must obey is basicallya <,> (b <,> c) == (a <,> b) <,> c(up to isomorphism). - Luis Casillas