【问题标题】:lifting trouble with ResourceT使用 ResourceT 解决问题
【发布时间】:2012-05-23 23:31:13
【问题描述】:

我正在调整这个example,尤其是客户端。我会告诉你我认为问题出在哪里,按照代码和它产生的错误。

> {-# LANGUAGE OverloadedStrings #-}
> import Network.HTTP.Conduit
> ( http, parseUrl, newManager,def, withManager, RequestBody (RequestBodyLBS)
> , requestBody, method, Response (..)
> )
> import Data.Aeson (Value (Object, String))
> import Data.Aeson.Parser (json)
> import Data.Conduit
> import Data.Conduit.Attoparsec (sinkParser)
> import Control.Monad.IO.Class (liftIO)
> import Control.Monad.Trans.Class (lift)
> import Data.Aeson (encode, (.=), object)


> main :: IO ()
> main = withManager $ \manager -> do
>    value <- makeValue
> -- We need to know the size of the request body, so we convert to a
> -- ByteString
>    let valueBS = encode value
>    req' <- parseUrl "http://10.64.16.6:3000/"
>    let req = req' { method = "POST", requestBody = RequestBodyLBS valueBS }
>    Response status version headers body <- http req manager
>    resValue <- body $$ sinkParser json
>    handleResponse resValue

> -- Application-specific function to make the request value
> makeValue :: ResourceT IO Value
> makeValue = return $ object
>    [ ("foo" .= ("bar" :: String))
>    ]

> -- Application-specific function to handle the response from the server
> handleResponse :: Value -> ResourceT IO ()
> handleResponse foo = do  
>    _ <- lift (print foo)
>    return ()

No instance for (Control.Monad.Trans.Class.MonadTrans ResourceT)
  arising from a use of `lift'
Possible fix:
  add an instance declaration for
  (Control.Monad.Trans.Class.MonadTrans ResourceT)
In a stmt of a 'do' block: _ <- lift (print foo)
In the expression:
  do { _ <- lift (print foo);
       return () }
In an equation for `handleResponse':
    handleResponse foo
      = do { _ <- lift (print foo);
             return () }

问题来了,错误提示没有 Control.Monad.Trans.Class.MonadTrans ResourceT 的实例

但我认为有,因为documentation。那么哪里出了问题?

如下所述,Control.Monad.Trans.Resource 出现了一些 janke 问题

这是ResourceT 内省的结果。

*Main Control.Monad.Trans.Resource> :i ResourceT
newtype ResourceT m a
  = Control.Monad.Trans.Resource.ResourceT (GHC.IORef.IORef
                                              Control.Monad.Trans.Resource.ReleaseMap
                                            -> m a)
    -- Defined in `Control.Monad.Trans.Resource'
instance Monad m => Monad (ResourceT m)
  -- Defined in `Control.Monad.Trans.Resource'
instance Functor m => Functor (ResourceT m)
  -- Defined in `Control.Monad.Trans.Resource'
instance MonadBaseControl b m => MonadBaseControl b (ResourceT m)
  -- Defined in `Control.Monad.Trans.Resource'
instance MonadThrow m => MonadThrow (ResourceT m)
  -- Defined in `Control.Monad.Trans.Resource'

resourcet 的版本是

[mlitchard@Boris Boris]$ ghc-pkg list resourcet
WARNING: there are broken packages.  Run 'ghc-pkg check' for more details.
/usr/lib/ghc-7.4.1/package.conf.d
/home/mlitchard/.ghc/x86_64-linux-7.4.1/package.conf.d
   resourcet-0.3.2.1

关于如何进行的任何想法? MonadTrans ResourceT 的实例在哪里?

【问题讨论】:

  • 使用以下代码,我现在得到了相同的结果!这很奇怪:foo :: ResourceT IO (); foo = lift $ return ()。它与错误的包数据库无关。
  • 我已经得出结论,这一定是 GHC 或其他系统中的错误。对此有更多了解的人可能会纠正我。
  • 我请包作者插话。
  • 我无法重现此问题:您的代码在这里编译得很好。您可能需要提供所有相关库和程序的具体版本:resourcetconduithttp-conduitghc

标签: haskell monads monad-transformers conduit


【解决方案1】:

如果我是一个赌徒,我会说你安装了某个库的多个版本。例如,假设您有 0.2 和 0.3 版本的转换器,并且 resourcet 是针对 0.2 版本构建的。当您编写代码 import Control.Monad.Trans.Class (lift) 时,您正在导入 lift 的 0.3 版,但没有涉及它的实例。

对此进行测试的最简单方法是修改代码。 Cabal 将确保您拥有相关库的正确版本。

【讨论】:

  • 配置 BorisTest-0.1.0.0... 构建 BorisTest-0.1.0.0... 为 BorisTest-0.1.0.0 预处理可执行文件“Boris_Test”... client.hs:12:8: 无法找到模块Control.Monad.Trans.Class' It is a member of the hidden package transformers-0.3.0.0'。也许您需要添加transformers' to the build-depends in your .cabal file. It is a member of the hidden package transformers-0.2.2.0'。也许您需要在 .cabal 文件中的 build-depends 中添加“transformers”。使用 -v 查看搜索的文件列表。
  • 故事的寓意,没有理由不每次都使用阴谋集团来处理任何严肃的事情。
【解决方案2】:

编辑:这个答案没有解决问题,导入仍然没有解决实例,即使它应该。这似乎是 GHC 或其他系统中的错误。

Data.Conduit 模块只是为了方便重新导出ResourceT;资源单子转换器在单独的包resourcet 中定义。 conduit 因此不会重新导出类实例(显然?)。您需要手动导入Control.Monad.Trans.Resource 才能访问关联的类实例。这当然可以使用以下语法来完成:

import Control.Monad.Trans.Resource () -- Only import instances

【讨论】:

  • 我将其标记为正确,因为它有意义。但是我的代码给出了完全相同的错误,就好像我从未添加过新的导入行一样。我什至删除了试图生成警告的()。没有警告
  • 您是否尝试将文件加载到ghci 并使用:i 显示有关ResourceT 的范围内信息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 2019-08-20
  • 2017-01-10
相关资源
最近更新 更多