我编写了一个简单的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)'
让我感到困惑的原因有两个:
resp <- runReaderT (handle a) defaultRequest
在GHCI中工作!为什么会这样?
答案 0 :(得分:2)
类型Application
定义为:
type Application = Request -> ResourceT IO Response
(ResourceT的原因是您可以分配稀缺资源并在发送流式响应时使用它们。这与基于大型数据库查询发回响应相关。但这与您的问题没有直接关系。 )
您的runReaderT (reader a)
类型为Request -> IO Response
。为了让它在ResourceT IO
中返回响应,似乎有两个选项:
app
:app = lift . runReaderT (reader a)
。 (lift
中定义了Control.Monad.Trans.Class
。)hanlde
的类型更改为handle :: (Resource a) => a -> ReaderT W.Request (ResourceT IO) W.Response
。如果您可能需要执行资源敏感操作,第一种方法是有意义的,而第二种方法可能是更容易的更改。