管道简单的文件读取表达式而不是类型检查

时间:2014-09-10 23:28:16

标签: haskell conduit

我正试图在我的腰带上找到一个简单的conduit示例,但我在类型检查阶段失败了。在this example中,我看到ResourceT被用作管道“执行者”,如果这是有道理的。我也知道,有一段时间ResourceTfactored-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的实例而遇到类型类错误。我应该如何解决这个问题?

1 个答案:

答案 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导入

liftIOControl.Monad.IO.Class