I slightly changed the app shown in the servant tutorial to make Reader
monad a ReaderT
, like so
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}
module Lib
( runServer
) where
import Control.Monad.Except
import Control.Monad.Reader
import qualified Data.Text as T
import Network.Wai
import Servant
type WebApi
= "static" :> Raw
:<|> "foo" :> Get '[PlainText] T.Text
type Foo = String
server :: ServerT WebApi (ReaderT Foo (ExceptT ServantErr IO))
server = static :<|> foo
where
static :: Application
static = undefined
-- Handler T.Text
foo :: ReaderT Foo (ExceptT ServantErr IO) T.Text
foo = undefined
webAPI :: Proxy WebApi
webAPI = Proxy
readerToHandler :: Foo -> ReaderT Foo (ExceptT ServantErr IO) :~> ExceptT ServantErr IO
readerToHandler t = Nat (\x -> runReaderT x t)
-- readerServer :: ServerT WebApi (ExceptT ServantErr IO)
-- readerServer = enter (readerToHandler "foobarbaz") server
-- serve' :: Application
-- serve' = serve webAPI server
runServer :: IO ()
runServer = return ()
The trouble is I can't enable readerServer
function, type checking fails with this inscrutable error
src/Lib.hs:45:16: error:
• Couldn't match type ‘IO’ with ‘ExceptT ServantErr IO’
arising from a functional dependency between:
constraint ‘Servant.Utils.Enter.Enter
(IO ResponseReceived)
(ReaderT Foo (ExceptT ServantErr IO) :~> ExceptT ServantErr IO)
(IO ResponseReceived)’
arising from a use of ‘enter’
instance ‘Servant.Utils.Enter.Enter (m a) (m :~> n) (n a)’
at <no location info>
• In the expression: enter (readerToHandler "foobarbaz") server
In an equation for ‘readerServer’:
readerServer = enter (readerToHandler "foobarbaz") server
Failed, modules loaded: none.
Any ideas what's going wrong?