module Control.Applicative.Plus ( withOptional , optional' , module Control.Applicative ) where import Control.Applicative import Control.Monad import qualified Data.Foldable as F {-# SPECIALIZE withOptional :: (a -> (b -> m c) -> m c) -> Maybe a -> (Maybe b -> m c) -> m c #-} withOptional :: (Foldable t, Alternative t) => (a -> (b -> m c) -> m c) -> t a -> (t b -> m c) -> m c withOptional withReq wrappedVal go = do let runAction = flip fmap wrappedVal $ \val -> withReq val $ \inner -> go (pure inner) emptyCase = go empty actionOrEmptyCase = F.foldl' (\_ a -> a) emptyCase runAction actionOrEmptyCase -- | A generalized version of 'optional' that works with 'Option' for example optional' :: (MonadPlus t, Alternative f) => f a -> f (t a) optional' x = flip fmap (optional x) $ \val -> case val of Just ok -> pure ok Nothing -> empty