module Control.Monad.Generator (
GeneratorT(..), generate, yield, breakGenerator
) where
import Control.Applicative (Applicative(..))
import Control.Monad (liftM, ap)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.ListT (ListT)
import Control.Monad.Trans.Class (MonadTrans(..))
import Control.Monad.Trans.Cont (ContT (..), mapContT)
import Data.List.Class (cons)
import Data.Monoid (Monoid(..))
newtype GeneratorT v m a =
GeneratorT { runGeneratorT :: ContT v (ListT m) a }
instance Monad m => Functor (GeneratorT v m) where
fmap = liftM
instance Monad m => Monad (GeneratorT v m) where
return = GeneratorT . return
GeneratorT a >>= f = GeneratorT $ a >>= runGeneratorT . f
fail = lift . fail
instance Monad m => Applicative (GeneratorT v m) where
pure = return
(<*>) = ap
instance MonadTrans (GeneratorT v) where
lift = GeneratorT . lift . lift
generate :: Monad m => GeneratorT v m () -> ListT m v
generate = (`runContT` const mempty) . runGeneratorT
modifyRes :: Monad m => (ListT m a -> ListT m a) -> GeneratorT a m ()
modifyRes = GeneratorT . (`mapContT` return ())
yield :: Monad m => v -> GeneratorT v m ()
yield = modifyRes . cons
breakGenerator :: Monad m => GeneratorT v m a
breakGenerator = GeneratorT . ContT . const $ mempty
instance MonadIO m => MonadIO (GeneratorT v m) where
liftIO = lift . liftIO