Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it really a default practice to make every monad transformer an instance of MonadTrans?

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)

like image 504
forker Avatar asked Sep 29 '15 22:09

forker


1 Answers

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.

like image 99
leftaroundabout Avatar answered Oct 20 '22 21:10

leftaroundabout