0

ReaderTを使用して次のようにリクエストへのアクセスを許可する単純なWAIアプリケーションを作成しました。

import qualified Network.Wai as W
handle :: (Resource a) => a -> ReaderT W.Request IO W.Response

ここhandleで、は処理の大部分を実行する関数です。次に、アプリケーションでそれを呼び出します。

app :: W.Application
app = runReaderT (handle a) -- simplified; i don't think the value of a matters

main :: IO ()
main = run 3000 app

しかしrunhaskell main.hs、私に次のことを与えます:

Couldn't match expected type `Control.Monad.Trans.Resource.ResourceT
                                IO'
            with actual type `IO'
Expected type: ReaderT
                 W.Request (Control.Monad.Trans.Resource.ResourceT IO) W.Response
  Actual type: ServerMonad W.Response
In the return type of a call of `handle'
In the first argument of `runReaderT', namely
  `(handle a)'

これは2つの理由で私を混乱させます:

  1. なぜそのタイプを期待しているのか分かりません
  2. 呼び出しresp <- runReaderT (handle a) defaultRequestはGHCIで機能します!

なぜこうなった?

4

1 に答える 1

2

タイプApplicationは次のように定義されます。

type Application = Request -> ResourceT IO Response

(ResourceTの理由は、不足しているリソースを割り当てて、ストリーミング応答を送信するときにそれらを使用できるようにするためです。これは、大規模なデータベースクエリに基づいて応答を返送する場合に関係します。ただし、質問には直接関係ありません。)

あなたのrunReaderT (reader a)タイプはRequest -> IO Response。で応答を返すResourceT IOようにするには、2つのオプションがあるようです。

  1. 持ち上げてappください:app = lift . runReaderT (reader a)。(liftで定義されていControl.Monad.Trans.Classます。)
  2. のタイプをhanldeに変更しhandle :: (Resource a) => a -> ReaderT W.Request (ResourceT IO) W.Responseます。

最初のアプローチは、リソースに依存する操作を実行する必要がある場合に意味がありますが、2番目のアプローチはおそらくより簡単な変更です。

于 2012-10-14T02:49:14.293 に答える