-
-
Notifications
You must be signed in to change notification settings - Fork 420
Closed
Description
Say, you have an API built according to https://docs.servant.dev/en/stable/cookbook/using-custom-monad/UsingCustomMonad.html
Now you additionally have a Raw endpoint and want access to the ReaderT environment in the handler, which now is of type Application and not Handler.
Whatever I tried, I could not make it work (of course, I can pass the environment explicitly to the server function so I can just runReaderT, but that's not the "using custom monad" approach).
Example code:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Concurrent.Chan
import Control.Monad.IO.Class
import Data.Proxy
import Servant.API
import Servant.Server
import Network.Wai
import Control.Monad.Trans.Reader
import Network.Wai.Handler.Warp ( run )
import Network.Wai.Internal
type AppM = ReaderT AppState Handler
type WaiApplicationM = Request -> (Response -> IO ResponseReceived) -> AppM ResponseReceived
data AppState = AppState (Chan Int)
type API = LOL :<|> WAI
type WAI = "wai" :> Raw
type LOL = "lol" :> Get '[JSON] [Int]
api :: Proxy API
api = Proxy
server :: ServerT API AppM
server = lol :<|> (Tagged waiHandler :: Tagged AppM WaiApplicationM)
where
waiHandler :: WaiApplicationM
waiHandler = \_ _ -> pure ResponseReceived
lol :: AppM [Int]
lol = do
liftIO $ putStrLn "lol"
return [1]
app :: Application
app = \req resp -> do
c <- newChan
serve api (hoistServer api (nt (AppState c)) $ server) req resp
where
nt :: AppState -> AppM a -> Handler a
nt s x = flip runReaderT s x
main :: IO ()
main = run 8081 appError:
app/Main.hs:36:10: error:
• Couldn't match type ‘ReaderT AppState Handler ResponseReceived’
with ‘IO ResponseReceived’
Expected type: ServerT API AppM
Actual type: AppM [Int] :<|> Tagged AppM WaiApplicationM
• In the expression:
lol :<|> (Tagged waiHandler :: Tagged AppM WaiApplicationM)
In an equation for ‘server’:
server
= lol :<|> (Tagged waiHandler :: Tagged AppM WaiApplicationM)
where
waiHandler :: WaiApplicationM
waiHandler = \ _ _ -> pure ResponseReceived
lol :: AppM [Int]
lol
= do liftIO $ putStrLn "lol"
....
|
36 | server = lol :<|> (Tagged waiHandler :: Tagged AppM WaiApplicationM)
Metadata
Metadata
Assignees
Labels
No labels