Gabriella439 / turtle

Shell programming, Haskell style

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

commented

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