7

Scotty を使用して非常に単純な API を構築しようとしています。ルート ハンドラー アクションが不変の環境にアクセスできるように、Scotty モナドを拡張したいと考えています。これを行う方法は、Readerモナドをスタックに追加することだと思います。Text今のところ、いくつかのデータを渡したいだけです。

Scotty モナドを次のように拡張しました。

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

だから私の最初の質問は、これは正しいアプローチですか?

ルート ハンドラのタイプを正常に変更しましたが、このスタックを使用して Scotty を起動する方法がわかりません。私は次のことを試みました:

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

しかし、私はエラーが発生します:

  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

2 つ目の質問は、別のモナド スタックで Scotty を起動するにはどうすればよいかということです。モナド変換子を使用するのはこれが初めての試みであり、絶望的に迷っているようです。

4

1 に答える 1

10

あなたのアプローチは問題ないようです。型エラーは、 (は を使用する場合のみで、その下にダミーのモナドがある)runReaderTではなく使用する必要があるためです。runReaderrunReaderReaderReaderTIdentity

于 2014-04-14T21:05:39.270 に答える