module MonadHelp 
    ( module Control.Monad
    , module MonadHelp
    ) where
import Control.Monad

untilJust :: Monad m => m (Maybe a) -> m a
untilJust m = go
  where
    go = do
        mayx <- m
        maybe go return mayx

untilJustCount :: Monad m => m (Maybe a) -> m (a, Int)
untilJustCount m = go 0
  where
    go i = do
        mayx <- m
        case mayx of
            Nothing -> go (i+1)
            Just x  -> return (x,i)

iterateUntil :: Monad m => (a -> Bool) -> m a -> m a
iterateUntil t m = do
    x <- m
    if t x 
        then return x
        else iterateUntil t m

iterateWhile :: Monad m => (a -> Bool) -> m a -> m a
iterateWhile t = iterateUntil (not . t)

unfoldrMID :: (Monad m) => (a -> m (Maybe a)) -> a -> m [a]
unfoldrMID f = go
  where
    go z = do
        x <- f z
        case x of
            Nothing -> return [z]
            Just y  -> (z :) <$> go y
