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

monadic hoistServerM? #1700

Closed
goertzenator opened this issue Aug 11, 2023 · 1 comment
Closed

monadic hoistServerM? #1700

goertzenator opened this issue Aug 11, 2023 · 1 comment

Comments

@goertzenator
Copy link

I have been experimenting MonadUnliftIO handlers under Servant with some success. Example. An essential component is unliftio's "toIO" function which looks like this:

toIO :: MonadUnliftIO m => m a -> m (IO a)

This is an effective way to get a IO a which with a little further massaging can be turned into Handler. But, this function has a monadic context so it does not work with hoistServer which has this signature:

hoistServer :: HasServer api '[] => Proxy api -> (forall x. m x -> n x) -> ServerT api m -> ServerT api n

What is needed in this situation is a monadic version of hoistServer that looks like this:

hoistServerM :: HasServer api '[] => Proxy api -> (forall x. m x -> m (n x)) -> ServerT api m -> m (ServerT api n)

I would like to experiment with an implementation that looks like this:

  1. Convert the existing implementations of hoistServerWithContext into hoistServerWithContextM.
  2. Add a hoistServerWithContext that wraps hoistServerWithContextM using Identity.

My example above demonstrates ReaderT, but my real motive is to enable ReaderT-based effect systems like cleff and effectful.

I am looking for some feedback on this idea. If I did a PR like this would it have any hope of being merged? Are there some obvious shortcomings here that I am not seeing?

As a reference, wai supports unliftio through the wai-control package.

Thank you for your time.

@goertzenator
Copy link
Author

The proposed solution has some serious problems and I would like to retract it.

Also, I've found a solution that involves no modification to Servant.

The main line is this one which hoists a ReaderT _ IO to Handler

  server <- withRunInIO $ \toIo -> pure $ hoistServer counterAPI (Handler . ExceptT . try . toIo) server_rio
  -- `toIO` converts from (ReaderT (IORef Int) IO) to IO
  -- `Handler. ExceptT . try` converts Servant exceptions in IO back to ExceptT

That of course will work with anything that is MonadUnliftIO such as the cleff and effectful Eff monad.

Closing this issue.

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

No branches or pull requests

1 participant