Is there an interface class that allows one to run the transformers to the base monad?
For example something like
class Run a b c | a -> c where
run :: a -> b -> c
instance Run (m (a, s)) b c => Run (StateT s m a) (s,b) c where
run x (s,b) = run (runStateT x s) b
instance Run (IO a) b (IO a) where
run = const
run (gets succ :: StateT Int (StateT String IO) Int) (1, ("abc", ()))
:: IO ((Int, String), Int)
-- ((2, "abc"), 1)
EDIT ADDITION:
I have improved upon the Run
class with RunBase
below. There could be more general instances without TestParameters
(test
class RunBase m b where
type BaseMonad m :: Type -> Type
type StM' m a :: Type
runBase :: m a -> b -> BaseResult m a
data TestParameters r s = TestParameters
{ filePath :: FilePath
, string :: String
, read :: r
, state :: s
}
instance RunBase m b => RunBase (IdentityT m) b where
type BaseMonad (IdentityT m) = BaseMonad m
type StM' (IdentityT m) a = StM' m a
runBase x b = runBase (runIdentityT x) b
instance RunBase m (TestParameters r s) => RunBase (ReaderT r m) (TestParameters r s) where
type BaseMonad (ReaderT _ m) = BaseMonad m
type StM' (ReaderT _ m) a = StM' m a
runBase x b@(TestParameters {read}) = runBase (runReaderT x read) b
instance RunBase m (TestParameters r s) => RunBase (LazyWriterT w m) (TestParameters r s) where
type BaseMonad (LazyWriterT _ m) = BaseMonad m
type StM' (LazyWriterT w m) a = StM' m (a, w)
runBase x b = runBase (Control.Monad.Trans.Writer.Lazy.runWriterT x) b
instance RunBase m (TestParameters r s) => RunBase (LazyStateT s m) (TestParameters r s) where
type BaseMonad (LazyStateT s m) = BaseMonad m
type StM' (LazyStateT s m) a = StM' m (a, s)
runBase x b@(TestParameters {state}) = runBase (Control.Monad.Trans.State.Lazy.runStateT x state) b
instance RunBase m (TestParameters r s) => RunBase (LazyRWST r w s m) (TestParameters r s) where
type BaseMonad (LazyRWST _ _ _ m) = BaseMonad m
type StM' (LazyRWST _ w s m) a = StM' m (a, s, w)
runBase x b@(TestParameters {read, state}) = runBase (Control.Monad.Trans.RWS.Lazy.runRWST x read state) b
instance RunBase IO b where
type BaseMonad IO = IO
type StM' IO a = a
runBase = const