scotty icon indicating copy to clipboard operation
scotty copied to clipboard

ScottyT does not have a MonadTrans instance

Open eborden opened this issue 6 years ago • 4 comments

It seems that ScottyT is defined as

newtype ScottyT e m a = ScottyT { runS :: State (ScottyState e m) a }

Is there a reason this isn't using StateT?

newtype ScottyT e m a = ScottyT { runS :: StateT (ScottyState e m) m a }

This would unlock MonadTrans and other useful instances within ScottyT and fulfill the T label on this type.

eborden avatar Jan 23 '19 22:01 eborden

The difference between m and n are the only blockers I can find for using StateT. Is there a reason these constraints are setup this way?

scottyT :: (Monad m, MonadIO n)
        => Port
        -> (m Response -> IO Response) -- ^ Run monad 'm' into 'IO', called at each action.
        -> ScottyT e m ()
        -> n ()

eborden avatar Jan 23 '19 22:01 eborden

i agree that this should be done. i'm not sure what should be done to fix the scottyT function. that function cannot evaluate the ScottyT argument in n, so it cannot really use execStateT just once, as it does now. i'll think on this.

chessai avatar Dec 19 '19 20:12 chessai

There are two problems:

  • ScottyT is not a monad transformer
  • Some code already relies on ScottyT being an IO-based monad

To make it a real transformer, a new name needs to be introduced, but that kinda kills the original motivation. Do you have any opinions?

fumieval avatar May 17 '21 08:05 fumieval

The difference between m and n are the only blockers I can find for using StateT. Is there a reason these constraints are setup this way?

scottyT :: (Monad m, MonadIO n)
        => Port
        -> (m Response -> IO Response) -- ^ Run monad 'm' into 'IO', called at each action.
        -> ScottyT e m ()
        -> n ()

@eborden I know it's been a few years :) But the reasonm and n are different is because ScottyT is essentially just a configuration effect for the server, whereas ActionT is where the exchange with the world takes place. If m == n we'd have to run the same effect both at every endpoint response and to run the overall server, which I think is what @chessai hinted at above. I'm now leaning towards a breaking change that adds a second type parameter to ScottyT: ScottyT n m a, and add a MonadTrans (ScottyT n) instance that way.

ocramz avatar Mar 10 '24 12:03 ocramz