{- Copyright (c) 2011 Robert Henderson
This source file is distributed under the terms of a BSD3-style
license, which can be found in the file LICENSE at the root of
this package. -}

-- | Extends "Control.Monad"
--
module Control.Monad.Rosso1
    (module Control.Monad

    ,nop

    ,concatMapM
    ,ifM
    ,whenM

    ) where

------------------------------------------------------
import Control.Monad


-- | Synonym for @return ()@
nop :: Monad m => m ()
nop = return ()



-- | Monadic generalisation of 'concatMap'.
concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM f = liftM concat . mapM f


-- | Monadic generalisation of 'if'.
ifM :: Monad m => m Bool -> m a -> m a -> m a
ifM t a b = do tVal <- t
               if tVal then a else b

-- | Like 'when', but the condition is also monadic.
whenM :: Monad m => m Bool -> m () -> m ()
whenM t a = do tVal <- t
               when tVal a



-----------------------------------------------------------
{- UNIT TESTS

*Rosso.Monad1e> concatMapM (\ x -> do y <- [1..x]; return [1..y]) [1..3]
[[1,1,1],[1,1,1,2],[1,1,1,2,3],[1,1,2,1],[1,1,2,1,2],[1,1,2,1,2,3]]

*Rosso.Monad1> ifM [True, False, True] "ab" "xyz"
"abxyzab"
*Rosso.Monad1> whenM [True, False, True] []
[()]
*Rosso.Monad1> whenM [True, False, True] [(), (), ()]
[(),(),(),(),(),(),()]

-}