Reputation: 52039
I'm looking for a more concise / idiomatic way of writing getAorB
:
getAorB = do
a <- getA
case a of
Just _ -> return a
Nothing -> getB
Does this already exist as a library function somewhere?
Note that liftM2 (<|>) getA getB
is the same as:
do a <- getA
b <- getB
return $ a <|> b
which is different from getAorB
since bind is always called on getB
even if getA
returns a Just
.
Upvotes: 2
Views: 119
Reputation: 664548
You can use the maybe
function (b -> (a -> b) -> Maybe a -> b
) with its default value:
getAorB :: Monad m => m a
getAorB = getA >>= maybe getB return
I don't think there's a single function that does this anywhere.
Trying to use an Alternative (such as MaybeT) doesn't work well here imo as it considers the second action to be fallible as well, which your getB
isn't. If it if was, you should consider using MaybeT
though:
getAorB :: Monad m => m (Maybe a)
getAorB = runMaybeT $ MaybeT getA <|> MaybeT getB
Upvotes: 2
Reputation: 152837
To hide all the transformers:
import Control.Monad.Trans.Maybe
getAOrB :: m (Maybe a) -> m (Maybe a) -> m (Maybe a)
getAOrB getA getB = runMaybeT (MaybeT getA <|> MaybeT getB)
But I would probably just use MaybeT
everywhere instead:
getAOrB' :: MaybeT m a -> MaybeT m a -> MaybeT m a
getAOrB' = (<|>)
Note that this type is slightly different than the type of your first implementation; it has the same type as your second implementation but better behavior.
Upvotes: 0
Reputation: 1441
Since (<|>) gets it's powers from applicative isn't this impossible? It feels like the type you are looking for is something like
Monad m => a ->[m (Maybe a)] -> m a
instead? Or maybe
Monad m => a -> (a -> Bool) -> [m a] -> m a
Hoogle doesn't give me anything for either.
Upvotes: 0