WAI应用程序可以使用ghci但不能使用runhaskell

时间:2012-10-14 00:30:22

标签: haskell monad-transformers haskell-wai

我编写了一个简单的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中工作!
  3. 为什么会这样?

1 个答案:

答案 0 :(得分: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. hanlde的类型更改为handle :: (Resource a) => a -> ReaderT W.Request (ResourceT IO) W.Response
  3. 如果您可能需要执行资源敏感操作,第一种方法是有意义的,而第二种方法可能是更容易的更改。