scotty-web / scotty

Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp (Official Repository)
http://hackage.haskell.org/package/scotty
BSD 3-Clause "New" or "Revised" License
1.72k stars 134 forks source link

ScottyT does not have a MonadTrans instance #225

Open eborden opened 5 years ago

eborden commented 5 years ago

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 commented 5 years ago

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 ()
chessai commented 4 years ago

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.

fumieval commented 3 years ago

There are two problems:

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?

ocramz commented 7 months ago

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.