In the question Web, Scotty: connection pool as monad reader it is shown how to use ScottyT
to embed a Reader
monad in the stack to access a static configuration (in that case, a connection pool).
I have a similar question, but simpler – or at least I thought so…
I want to add a Reader
to a single handler (i.e. a ActionT
), not the whole app.
I started modifying the program from the question above, but I cannot figure out how to turn an ActionT Text (ReaderT String IO)
into the ActionT Text IO
the handler needs to be. After fumbling around and trying to use typed holes hoping to see how to construct this I have to give up for now and ask for help. I really feel this should be simple, but cannot figure out how to do this.
Here's the program, with the lines where I'm stuck highlighted:
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text.Lazy as T
import Data.Text.Lazy (Text)
import Control.Monad.Reader
import Web.Scotty.Trans
type ActionD = ActionT Text (ReaderT String IO)
main :: IO ()
main = do
scottyT 3000 id id app
-- Application
app :: ScottyT Text IO ()
app = do
get "/foo" $ do
h <- handler -- ?
runReaderT h "foo" -- ?
--get "/bar" $ do
-- h <- handler
-- runReaderT h "bar"
-- Route action handler
handler :: ActionD ()
handler = do
config <- lift ask
html $ T.pack $ show config
ActionT
and rebuild it. However, that type is opaque, so we can not... – chiReader
can be used instead. – betat1 (t2 m) a
intot1 m a
, wheret1,t2
are monad transformers. Or, more generically,t m1 a
intot m2 a
wherem1,m2
are monads. This looks as a functor-ish requirement ont
: givenf :: forall b. m1 b -> m2 b
you would like to havefmapT f :: t m1 a -> t m2 a
. Maybe not all transformers would allowfmapT
but this could be a typeclass on its own. Or maybe there's some way to craft it with standard tools I am not seeing right now :-/ – chi