0

我编写了一个简单的 WAI 应用程序,它使用 ReaderT 来允许访问请求,如下所示:

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

这让我感到困惑有两个原因:

  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,似乎有两种选择:

  1. 提起它appapp = lift . runReaderT (reader a)。(lift在 中定义Control.Monad.Trans.Class。)
  2. 将类型更改hanldehandle :: (Resource a) => a -> ReaderT W.Request (ResourceT IO) W.Response

如果您可能需要执行对资源敏感的操作,则第一种方法很有意义,而第二种方法可能更容易进行更改。

于 2012-10-14T02:49:14.293 回答