{-# LANGUAGE OverlappingInstances, FunctionalDependencies, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
module Control.Monad.ST.Class where

import GHC.IOBase(ioToST)
import Control.Monad.ST(RealWorld, ST)
import Control.Monad.Maybe
import Control.Monad.List
import qualified Control.Monad.State.Lazy as LazyS
import qualified Control.Monad.State.Strict as StrictS
import Control.Monad.Reader
import Data.Monoid(Monoid)
import qualified Control.Monad.Writer.Lazy as LazyW
import qualified Control.Monad.Writer.Strict as StrictW

-- | Type class of monads that can perform lifted computation in the 'ST' monad.
class Monad m => MonadST s m | m -> s where
	liftST :: ST s a -> m a

instance MonadST s (ST s) where
	liftST m = m

instance MonadST s m => MonadST s (LazyS.StateT s' m) where
	liftST = lift . liftST

instance MonadST s m => MonadST s (StrictS.StateT s' m) where
	liftST = lift . liftST

instance MonadST s m => MonadST s (ReaderT r m) where
	liftST = lift . liftST

instance (Monoid w, MonadST s m) => MonadST s (LazyW.WriterT w m) where
	liftST = lift . liftST

instance (Monoid w, MonadST s m) => MonadST s (StrictW.WriterT w m) where
	liftST = lift . liftST

instance MonadST s m => MonadST s (MaybeT m) where
	liftST = lift . liftST

instance MonadST s m => MonadST s (ListT m) where
	liftST = lift . liftST