Lift to Maybe using a predicate

后端 未结 2 577
广开言路
广开言路 2020-12-20 20:17

I\'m searching for something like

liftPredMaybe :: (a -> Bool) -> a -> Maybe a
liftPredMaybe p a
  | p a = Just a
  | otherwise = Nothing

相关标签:
2条回答
  • 2020-12-20 20:30

    One way to compose it is like this, using Control.Monad:

    liftPredM :: MonadPlus m => (a -> Bool) -> a -> m a
    liftPredM p = mfilter p . return
    

    Another alternative is to use Data.Foldable:

    liftPredF :: (a -> Bool) -> a -> Maybe a
    liftPredF f = find f . pure
    

    This is, however, less general, so I'd lean towards favouring the MonadPlus-based implementation.

    In both cases, though, the idea is to first lift a 'naked' value into a container using either pure or return, and then apply a filter. Often, you don't need to declare an actual function for this; instead, you can just inline the composition where you need it.

    Examples:

    Prelude Control.Monad> liftPredMaybe even 42 :: Maybe Integer
    Just 42
    Prelude Control.Monad> liftPredMaybe (even . length) "foo" :: Maybe String
    Nothing
    Prelude Control.Monad> liftPredMaybe (odd . length) "foo" :: Maybe String
    Just "foo"
    
    0 讨论(0)
  • 2020-12-20 20:46

    Not quite a ready-made solution, but with guard (from Control.Monad) and (<$) (from Data.Functor) we can write:

    ensure :: Alternative f => (a -> Bool) -> a -> f a
    ensure p a = a <$ guard (p a)
    

    (Thanks to Daniel Wagner for suggesting a nice name for this function.)

    A more pointfree spelling of dubious taste is \p -> (<$) <*> guard . p.

    0 讨论(0)
提交回复
热议问题