我有一个简单的任务-从文件中读取一堆行,并对每一行执行一些操作。除了第一个--这是一些可以忽略的标题。
所以我想我应该试试管道。
printFile src = runResourceT $ CB.sourceFile src =$=
CT.decode CT.utf8 =$= CT.lines =$= CL.mapM_ putStrLn凉爽的。
所以现在我只想把第一行...似乎有一个函数可以解决这个问题-
printFile src = runResourceT $ CB.sourceFile src =$=
CT.decode CT.utf8 =$= CT.lines =$= drop 1 =$= CL.mapM_ putStrLn嗯-但是现在我注意到drop有类型签名Sink a m ()。有人建议我可以使用管道的Monad实例,并使用drop有效地删除一些元素-所以我尝试了以下方法:
drop' :: Int -> Pipe a a m ()
drop' n = do
CL.drop n
x <- await
case x of
Just v -> yield v
Nothing -> return ()它不会进行类型检查,因为管道的monad实例只适用于相同类型的管道- Sinks的输出是Void,所以我不能这样使用它。
我快速查看了pipes和pipes-core,并注意到pipes-core具有我期望的功能,其中as pipes是一个最小的库,但文档显示了它将如何实现。
所以我很困惑--也许我遗漏了一个关键概念..我看到了这个函数
sequence :: Sink input m output -> Conduit input m output但这似乎不是正确的想法,因为输出值是()
CL.sequence (CL.drop 1) :: Conduit a m () 我可能只会回去使用lazy-io,因为我并不真的需要任何流媒体--但我很有兴趣看看正确的方法。
发布于 2012-05-31 23:21:19
首先,简单的回答:
... =$= CT.lines =$= (CL.drop 1 >> CL.mapM_ putStrLn)更详细的解释是:实际上有两种不同的方法可以实现drop。无论采用哪种方法,它都会首先从输入中删除n元素。关于它的下一步操作,有两种选择:
中的所有剩余项
前者是Sink将执行的行为(以及我们的drop实际执行的操作),而后者是Conduit的行为。实际上,您可以通过一元组合从前者生成后者:
dropConduit n = CL.drop n >> CL.map id然后,您可以使用dropConduit,正如您在开头所描述的。这是演示一元合成和融合之间区别的一种好方法;前者允许两个函数在同一个输入流上操作,而后者允许一个函数向另一个函数提供流。
我还没有进行基准测试,但我相当确定一元组合将会更有效率。
https://stackoverflow.com/questions/10834773
复制相似问题