bdcs-0.1.0: src/BDCS/Utils/Monad.hs
{-# LANGUAGE LambdaCase #-}
-- |
-- Module: BDCS.Utils.Monad
-- Copyright: (c) 2016-2017 Red Hat, Inc.
-- License: LGPL
--
-- Maintainer: https://github.com/weldr
-- Stability: alpha
-- Portability: portable
--
-- Monad related utility functions
module BDCS.Utils.Monad(concatForM,
concatMapM,
foldMaybeM,
mapMaybeM,
(>>?))
where
import Data.Maybe(catMaybes)
-- | Like 'Data.List.concatMap', but with its arguments reversed (the list comes
-- first and the function comes second) and operates in a monad.
concatForM :: (Monad m, Traversable t) => t a -> (a -> m [b]) -> m [b]
concatForM lst fn = fmap concat (mapM fn lst)
-- | Like 'Data.List.concatMap' but operates in a monad.
concatMapM :: (Monad m, Traversable t) => (a -> m [b]) -> t a -> m [b]
concatMapM fn lst = fmap concat (mapM fn lst)
-- | Like 'Data.Maybe.mapMaybe' but operates in a monad.
mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM fn = fmap catMaybes . mapM fn
-- Like 'Control.Monad.foldM', but skip Nothing results.
foldMaybeM :: Monad m => (b -> a -> m (Maybe b)) -> b -> [a] -> m b
foldMaybeM _ acc [] = return acc
foldMaybeM action acc (x:xs) = do
result <- action acc x
case result of
-- skip this element, continue with the original accumulator
Nothing -> foldMaybeM action acc xs
-- Keep this one
Just r -> foldMaybeM action r xs
-- | Apply a function to a monadic action. If the action is 'm Nothing', do nothing. Otherwise, apply the
-- function and return the result as 'm (Just a)'.
infixl 1 >>?
(>>?) :: Monad m => m (Maybe a) -> (a -> m b) -> m (Maybe b)
(>>?) input action = input >>= \case
Nothing -> return Nothing
Just x -> Just <$> action x