Skip to content

Instantly share code, notes, and snippets.

@dmwit
Created July 2, 2019 15:28
Show Gist options
  • Save dmwit/ce531720746377e683385341071d0318 to your computer and use it in GitHub Desktop.
Save dmwit/ce531720746377e683385341071d0318 to your computer and use it in GitHub Desktop.
With MonadReader (and other mtl classes), one thing you can't do is polymorphically reach "under" a given part of the transformer stack. For example, there's no polymorphic way to say "I want to run `ask`, but not the outer-most `ask`, the next one down". Here's an idea for how to have that possibility.
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
import Control.Monad.Reader (ReaderT)
import Control.Monad.State (StateT)
import qualified Control.Monad.Reader as R
import qualified Control.Monad.State as S
class Monad m => DmwitMonadReader m where
type Env m
type Wrapped m :: * -> *
ask :: m (Env m)
liftReader :: Wrapped m a -> m a
instance Monad m => DmwitMonadReader (ReaderT r m) where
type Env (ReaderT r m) = r
type Wrapped (ReaderT r m) = m
ask = R.ask
liftReader = R.lift
instance DmwitMonadReader m => DmwitMonadReader (StateT s m) where
type Env (StateT s m) = Env m
type Wrapped (StateT s m) = Wrapped m
ask = S.lift ask
liftReader = S.lift . liftReader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment