9
votes

So Real World Haskell says:

Every monad transformer is an instance of MonadTrans

but I'm playing with Scotty and found out that its base monad transformer ScottyT is not an instance of MonadTrans.

Looking at the release notes it seems that it is a deliberate design decision: here. Quote:

The monad parameters to ScottyT have been decoupled, causing the type of the ScottyT constructor to change. As a result, ScottyT is no longer a MonadTrans instance ...

I hope you understand my confusion. Nevertheless, I will try to formulate strict questions:

  • Why would one not want a monad transformer to be an instance of MonadTrans?
  • How would you explain the aforementioned change in ScottyT design?

P.S.: I do understand that I can define an instance of MonadTrans ScottyT myself, but should I? (links back to questions)

1
Perhaps the question is "Is ScottyT a monad transformer if it isn't an instance of MonadTrans?"crockeea
Thanks, Eric, I had it popping in my head, but if you look f.x. at en.wikibooks.org/wiki/Haskell/Monad_transformers it never states that MonadTrans is a prerequisite for somethingT to be a monad tranformer. It is more phrased as nice to have. check the line: Technically, this is all we need; however, it is convenient to make MaybeT an instance of a few other classesforker

1 Answers

10
votes

ScottyT is not a monad transformer. Let's inline the (simplified) definition:

newtype ScottyT' m a = ScottyT' {
   runS :: State [ (Request->m Response) -> Request->m Response ] a
  }

To define lift for this you would need, from a general m a action and such a middlewares list, have to obtain an actual a value, because State s yields actual unmonadic values. There's no way to do that.

Now, if you argue that MonadTrans isn't actually required for something to be a monad transformer: mathematically speaking, monad transformers correspond to a composition of functors, but ScottyT doesn't actually implement such a composition.