{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE UndecidableInstances   #-}
{-# LANGUAGE CPP   #-}
module Control.Monad.Gen.Class where
-- Import the non-depricated one
#if MIN_VERSION_mtl(2, 2, 1)
import           Control.Monad.Except
#else
import           Control.Monad.Trans.Error
#endif

import           Control.Monad.Cont
import           Control.Monad.List
import           Control.Monad.RWS
import           Control.Monad.Reader
import           Control.Monad.State
import qualified Control.Monad.State.Strict as SS
import           Control.Monad.Trans.Identity
import           Control.Monad.Trans.Maybe
import           Control.Monad.Writer
import qualified Control.Monad.Writer.Strict as SW

-- | The MTL style class for generating fresh values
class Monad m => MonadGen e m | m -> e where
  -- | Generate a fresh value @e@, @gen@ should never produce the
  -- same value within a monadic computation.
  gen :: m e

instance MonadGen e m => MonadGen e (IdentityT m) where
  gen :: IdentityT m e
gen = m e -> IdentityT m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (StateT s m) where
  gen :: StateT s m e
gen = m e -> StateT s m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (ReaderT s m)  where
  gen :: ReaderT s m e
gen = m e -> ReaderT s m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance (MonadGen e m, Monoid s) => MonadGen e (WriterT s m)  where
  gen :: WriterT s m e
gen = m e -> WriterT s m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (ListT m) where
  gen :: ListT m e
gen = m e -> ListT m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (MaybeT m) where
  gen :: MaybeT m e
gen = m e -> MaybeT m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (ContT r m) where
  gen :: ContT r m e
gen = m e -> ContT r m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance (Monoid w, MonadGen e m) => MonadGen e (RWST r w s m) where
  gen :: RWST r w s m e
gen = m e -> RWST r w s m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance MonadGen e m => MonadGen e (SS.StateT s m) where
  gen :: StateT s m e
gen = m e -> StateT s m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
instance (Monoid w, MonadGen e m) => MonadGen e (SW.WriterT w m) where
  gen :: WriterT w m e
gen = m e -> WriterT w m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen

#if MIN_VERSION_mtl(2, 2, 1)
instance (MonadGen e m) => MonadGen e (ExceptT e' m) where
  gen :: ExceptT e' m e
gen = m e -> ExceptT e' m e
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m e
forall e (m :: * -> *). MonadGen e m => m e
gen
#else
instance (MonadGen e m, Error e') => MonadGen e (ErrorT e' m) where
  gen = lift gen
#endif