Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add the Reader monad to Scotty's monad?

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.

like image 604
stusmith Avatar asked Apr 14 '14 20:04

stusmith


Video Answer


1 Answers

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).

like image 89
duplode Avatar answered Sep 19 '22 13:09

duplode