I have a tuple with a Maybe Int
in the second place. If this value is nothing, then the entire tuple is useless and should be discarded. I'd like to sequence over the tuple to bring the Maybe context out of the second place to envelop the entire tuple.
The signature of what I'm looking to do might be:
Monad m => (a, mb) -> m(a, b)
but I was unable to find anything similar on Hoogle.
I've read Haskell -- Is there a monad sequence function for tuples?, but it does not address the need.
https://hackage.haskell.org/package/tuple-0.3.0.2/docs/Data-Tuple-Sequence.html can only handle the case where the tuples are all wrapped in monad. I.e., Monad m => (ma, mb) -> m(a, b)
.
I can achieve this with a lambda function that tests the second element of the tuple and produces the appropriate response, but I'm wondering if there's an existing tool that does the job.
CodePudding user response:
This is just ordinary sequence
on pairs. The traversable is (,) a
, and the second element is the thing that gets traversed.
ghci> sequence ('a', Just 3)
Just ('a',3)
ghci> sequence ('a', Nothing)
Nothing
CodePudding user response:
As you've pointed out, you can do it yourself for Maybe
.
sequenceMaybe :: (a, Maybe b) -> Maybe (a, b)
sequenceMaybe (_, Nothing) = Nothing
sequenceMaybe (a, Just b) = Just (a, b)
And, in fact, we can generalize this to arbitrary monads pretty easily. In fact, we don't even need Monad
; we just need Functor
.
sequenceTuple :: Functor f => (a, f b) -> f (a, b)
sequenceTuple (a, fb) = fmap ((,) a) fb
If you really want a library function, then you've already found it: SequenceT
. You have a (a, m b)
, and SequenceT
wants a (m a, m b)
. It's trivial to wrap values which are not monadic in monadic context: that's what return
does (or pure
, for Applicative
).
sequenceTuple' :: Applicative f => (a, f b) -> f (a, b)
sequenceTuple' (a, fb) = sequenceT (pure a, fb)
But that's bringing a nuclear warhead to a knife fight. The sequenceTuple
is going to be quick and to-the-point. And it works on arbitrary Functor
instances.