Feature request: mapMaybe
GregorySchwartz opened this issue · comments
I find myself doing fromJust . filter isJust . fmap f
, where f :: a -> Maybe b
. Is it possible to have a mapMaybe
-like function for this to avoid importing and using partial functions?
@GregorySchwartz: What is the type signature that you expect for this utility?
(a -> Maybe b) -> Shell a -> Shell b
. Or, preferably, have an instance of Shell that would accomplish the same task (and more through generalization).
Does this do what you want?
filterShell :: (a -> Maybe b) -> Shell a -> Shell b
filterShell p s = s >>= select . p
It seems like this doesn't have to be turtle
-specific. This utility could be generalized to any MonadPlus
:
example :: MonadPlus m => (a -> Maybe b) -> m a -> m b
example f m = do
a <- m
case f a of
Nothing -> mzero
Just b -> return b
I'm actually surprised that there's not already something like this in Control.Monad
.
Wouldn't the more general function be the following ?
example2 :: MonadPlus m => m (Maybe a) -> m a
example2 m = do
a <- m
case a of
Nothing -> mzero
Just b -> return b
Then example f m = example2 $ fmap f m
Yes, that would be perfect (although simplier than I thought it would be, which is always a good thing!).
@GregorySchwartz: Could you try to see if this could be added to base
? If they turn it down, though, then I can add it to turtle
This exists as the mapMaybe
method of Filterable
in witherable
.
It seems the WrappedFoldable
instance is the one wanted here (perhaps via DerivingVia
?):
mapMaybe :: (Foldable f, Alterative f) => (a -> Maybe b) -> f a -> f b
mapMaybe f =
foldr (\x xs -> case p x of {Just a -> pure a <|> xs; _ -> xs}) empty