--------------------------------------------------------------------------------
--                                                                            --
-- general monadic utilities                                                  --
--                                                                            --
--------------------------------------------------------------------------------

-- many

many1 :: MonadPlus m => m x -> m [x]
many1 mx = do { x <- mx ; xs <- many mx ; result (x:xs) }

many :: MonadPlus m => m x -> m [x]
many mx = many1 mx ++ result [] 

-- list

list1 :: MonadPlus m => m s -> m x -> m [x]
list1 ms mx
  = do { x <- mx ; xs <- many msx ; result (x:xs) }
   where
    msx = do { ms ; x <- mx ; result x }

list :: MonadPlus m => m s -> m x -> m [x]
list ms mx = list1 ms mx ++ result []

-- doAll

doAll :: Monad m => [m ()] -> m ()
doAll [] = result ()
doAll (m:ms) = do { m ; doAll ms }

doAllSepWith :: Monad m => m s -> [m ()] -> m ()
doAllSepWith n [] = result ()
doAllSepWith n [m] = m
doAllSepWith n (m:ms) = do { m ; n ; doAllSepWith n ms }     

-- doWhile
                                       
doWhile :: Monad m => (x -> Bool) -> m x -> m [x]
doWhile p mx
  = do { x <- mx ;
         if p x 
          then do { xs <- doWhile p mx ; result (x:xs) }
          else result [] } 

-- forever

forever :: Monad m => m x -> m ()
forever m = do { m ; forever m }       
                                     
-- Monoid class 

class Monoid s where
  e :: s
  (|+|) :: s -> s -> s

instance Monad m => Monoid (m ()) where
  e = result ()
  m |+| n = do { m ; n }   
    
--------------------------------------------------------------------------------
