turtle icon indicating copy to clipboard operation
turtle copied to clipboard

Feature request: mapMaybe

Open GregorySchwartz opened this issue 5 years ago • 8 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 avatar Nov 05 '19 20:11 GregorySchwartz

@GregorySchwartz: What is the type signature that you expect for this utility?

Gabriella439 avatar Nov 05 '19 20:11 Gabriella439

(a -> Maybe b) -> Shell a -> Shell b. Or, preferably, have an instance of Shell that would accomplish the same task (and more through generalization).

GregorySchwartz avatar Nov 06 '19 14:11 GregorySchwartz

Does this do what you want?

filterShell :: (a -> Maybe b) -> Shell a -> Shell b
filterShell p s = s >>= select . p

int-index avatar Nov 06 '19 16:11 int-index

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.

Gabriella439 avatar Nov 06 '19 16:11 Gabriella439

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

miguel-negrao avatar Nov 06 '19 17:11 miguel-negrao

Yes, that would be perfect (although simplier than I thought it would be, which is always a good thing!).

GregorySchwartz avatar Nov 14 '19 19:11 GregorySchwartz

@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

Gabriella439 avatar Nov 14 '19 20:11 Gabriella439

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

hseg avatar Sep 12 '21 11:09 hseg