我正试图在我的腰带上找到一个简单的conduit示例,但我在类型检查阶段失败了。在this example中,我看到ResourceT
被用作管道“执行者”,如果这是有道理的。我也知道,有一段时间ResourceT
已factored-out into it's own package。但是,我仍然无法得到一个简单的例子。这是我的代码,其灵感来自this article:
import qualified Data.Conduit as C
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.List as CL
import Control.Monad.Trans.Resource (runResourceT)
import Data.ByteString.Char8 (unpack)
import Data.ByteString (ByteString (..))
import System.IO
printFile file = runResourceT $ CB.sourceFile file C.$$ print'
where
print' :: C.Sink ByteString IO ()
print' = CL.mapM_ $ putStrLn · unpack
这是我得到的错误(我的包名为“conduit-playground”:
Preprocessing library conduit-playground-0.0.0...
[2 of 2] Compiling Playground ( src/Playground.hs, dist/dist-sandbox-13da96d6/build/Playground.o )
src/Playground.hs:12:57:
Couldn't match type ‘IO’
with ‘Control.Monad.Trans.Resource.Internal.ResourceT m’
Expected type: C.Sink
ByteString (Control.Monad.Trans.Resource.Internal.ResourceT m) ()
Actual type: C.Sink ByteString IO ()
Relevant bindings include
printFile :: FilePath -> m () (bound at src/Playground.hs:12:1)
In the second argument of ‘(C.$$)’, namely ‘print'’
In the second argument of ‘($)’, namely
‘CB.sourceFile file C.$$ print'’
cabal: Error: some packages failed to install:
conduit-playground-0.0.0 failed during the building phase. The exception was:
ExitFailure 1
如果我遗漏runResourceT
,我仍然会因为MonadResource
没有IO
的实例而遇到类型类错误。我应该如何解决这个问题?
答案 0 :(得分:4)
问题是您的print'
具有不兼容的类型
print' :: C.Sink ByteString IO ()
如果您使用IO
(在这种情况下您需要读取文件),则不能将ResourceT
作为管道的基本monad。允许您打印和处理文件资源的最简单的monad是ResourceT IO
,即使用IO
转换器转换的ResourceT
monad。
print' :: C.Sink ByteString (ResourceT IO) ()
print' = CL.mapM_ $ liftIO . putStrLn · unpack
需要liftIO
才能将IO ()
类型的表达式“提升”为ResourceT IO ()
。您还可以使用更通用的签名
print' :: MonadIO m => C.Sink ByteString m ()
创建一个适用于任何能够执行IO的管道的实用程序功能。
可以从模块MonadIO
导入 liftIO
和Control.Monad.IO.Class
。