Question

I'm trying to use Scotty to build a very simple API. I'd like to extend the Scotty monads such that my route handler actions are able to access an unchanging environment. I believe the way to do this would be to add a Reader monad to the stack. For now I just want to pass some Text data around.

I've extended the Scotty monads as follows:

type BrandyScottyM = ScottyT TL.Text (ReaderT T.Text IO)
type BrandyActionM = ActionT TL.Text (ReaderT T.Text IO)

https://github.com/stu-smith/Brandy/blob/0838a63537d7e396ac82d58d460c6529349303d3/src/Core.hs

So my first question is, is this the correct approach?

I've successfully changed the types of my route handlers, but I can't work out how to launch Scotty using this stack. I've attempted the following:

runScotty :: Port -> Text -> BrandyScottyM () -> IO ()
runScotty port file = T.scottyT port ((\f -> runReader f file)) id

https://github.com/stu-smith/Brandy/blob/0838a63537d7e396ac82d58d460c6529349303d3/src/Main.hs

But I get the error:

  Couldn't match type `IO' with `Data.Functor.Identity.Identity'
    Expected type: Reader Text (IO a)
      Actual type: ReaderT Text IO a
    In the first argument of `runReader', namely `f'
    In the expression: runReader f file
    In the second argument of `T.scottyT', namely
      `((\ f -> runReader f file))'
/home/stu/git/Brandy/src/Main.hs: line 36, column 65:
  Couldn't match type `ReaderT Text IO Network.Wai.Internal.Response'
                  with `IO Network.Wai.Internal.Response'
    Expected type: ReaderT Text IO Network.Wai.Internal.Response
                   -> IO Network.Wai.Internal.Response
      Actual type: ReaderT Text IO Network.Wai.Internal.Response
                   -> ReaderT Text IO Network.Wai.Internal.Response
    In the third argument of `T.scottyT', namely `id'
    In the expression: T.scottyT port ((\ f -> runReader f file)) id
    In an equation for `runScotty':
        runScotty port file = T.scottyT port ((\ f -> runReader f file)) id

So my second question is, how do I launch Scotty with a different monad stack? This is my first attempt at using monad transformers and I seem to be hopelessly lost.

Was it helpful?

Solution

Your approach looks okay. The type error is because you should use runReaderT rather than runReader (runReader is only for when you use Reader, which is ReaderT with just the dummy Identity monad below it).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top