Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScottyT does not have a MonadTrans instance #225

Open
eborden opened this issue Jan 23, 2019 · 4 comments
Open

ScottyT does not have a MonadTrans instance #225

eborden opened this issue Jan 23, 2019 · 4 comments

Comments

@eborden
Copy link

eborden commented Jan 23, 2019

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
Copy link
Author

eborden commented Jan 23, 2019

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
Copy link
Contributor

chessai commented Dec 19, 2019

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
Copy link
Collaborator

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?

@ocramz
Copy link
Collaborator

ocramz commented Mar 10, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants