turtle
turtle copied to clipboard
Feature request: mapMaybe
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