Home > Net >  Is there ReaderT raised into a monad?
Is there ReaderT raised into a monad?

Time:08-26

I've written the following monad transformers (which I believe are equivalent to each other), namely:

newtype MonadReaderT1 r m a = MonadReaderT (ReaderT (r m) m a)
newtype MonadReaderT2 r m a = MonadReaderT (ReaderT (m r) m a)

The purpose of these is that I basically want a ReaderT, but my environment has to be accessed inside the Monad, it's not actually a fixed pure value (in my case, it's an auth token that needs to be periodically refreshed).

The reason why I think MonadReaderT1 and MonadReaderT2 are equivalent, because I can just go:

newtype B m = B (m A)

And then MonadReaderT1 B is the same as MonadReaderT2 A.

But I think I need this extra machinery here above and beyond what I get with plain old ReaderT.

But I get the feeling I'm not the first person to have done this or needed this. Have I just reinvented an existing type, and if so what is it?

CodePudding user response:

I'm not sure it's worth defining a separate transformer in this case. Consider that if you were using a reader transformer with an Int environment, you probably wouldn't feel a need to write a special transformer for this case:

newtype IntReaderT m a = IntReaderT (ReaderT Int m a)

Instead, you'd just use the ReaderT Int directly.

Similarly, if you happen to want a monadic action as your environment, I think you should just use the ReaderT directly, defining your monad stack as either a type:

type M = ReaderT (IO Token) IO

or a newtype:

newtype M a = M { unM :: ReaderT (IO Token) IO a }

along with a helper to fetch the token:

token :: M Token
token = ask >>= liftIO

If you prefer to write in a style that makes heavy use of mtl constraints, you can instead define token using a class and instance:

class MonadToken token m where
  token :: m token
instance MonadToken Token M where
  token = ask >>= liftIO

which allows you to write generic token-using monadic actions:

authorized :: (MonadToken token m) => m Bool
authorized = do
  t <- token
  ...

without actually having to define a new transformer.

  • Related