-- | Monadic combinators missing from the standard library
module Control.Monad.TM
(
  (.=<<.)
,  (.>>=.)
, anyM
, allM
) where

import Data.Traversable
import Control.Monad hiding (mapM)
import Prelude hiding (mapM)

-- | Lifting bind into a monad. Often denoted /concatMapM/.
(.=<<.) ::
  (Monad q, Monad m, Traversable m) =>
  (a -> q (m b))
  -> m a
  -> q (m b)
(.=<<.) f =
  liftM join . mapM f

-- | Lifting bind into a monad. Often denoted /concatMapM/.
(.>>=.) ::
  (Monad q, Monad m, Traversable m) =>
  m a
  -> (a -> q (m b))
  -> q (m b)
(.>>=.) =
  flip (.=<<.)

-- | Existential quantification.
anyM ::
  Monad m =>
  (a -> m Bool)
  -> [a]
  -> m Bool
anyM _ []     =
  return False
anyM f (a:as) =
  do z <- f a
     if z
       then return True
       else anyM f as

-- | Universal quantification.
allM ::
  Monad m =>
  (a -> m Bool)
  -> [a]
  -> m Bool
allM _ []     =
  return True
allM f (a:as) =
  do z <- f a
     if z
       then allM f as
       else return False