-- | Some useful monadic combinators missing from the standard libraries
module Monad.Util where
import Control.Monad(ap,when)

infixl 1 #,#!,<#

-- | Apply a pure function to the result of a monadic computation
f # x = fmap f x

-- | Apply a function returned by a monadic computation to an argument returned
-- by a monadic computation
f <# x = ap f x

-- | Perform two monadic computation and return the result from the second one
x #! y = const # x <# y


-- It is a scandal that monadic composition isn't defined in the libraries...
infixr 1 @@
-- | Kleiski composition
(m1 @@ m2) i = m1 =<< m2 i

-- | Infinite loops
loop m = l where l = m>>l

-- | While loops
whileM cndM bodyM = loop
  where loop = do more <- cndM
		  when more (bodyM >> loop)

-- | Repeat m while it returns True
repeatM m = whileM m (return ())

done :: Monad m => m ()
done = return ()