2017-06-02 64 views
2

使用管道,其给出:了解`conduit`输出

Prelude> :t (yieldMany [1..10] .| mapC show .| mapC print .| sinkList) 
(yieldMany [1..10] .| mapC show .| mapC print .| sinkList) 
    :: Monad m => ConduitM a c m [IO()] 

为什么没有任何输出得到记录?

Prelude> runConduit $ yieldMany [1..10] .| mapC show .| mapC print .| sinkList 
Prelude> 

我的期望是,为[1..10]的流,每个元素的String,即show,值将被打印。

请解释这个输出。

+2

IIRC,您在最近的CR问题中遇到类似问题。遇到像这样的问题时,请使用带有类型注释的适当源文件。您经常会注意到,当使用'IO'时,GHCi有点不同。如果添加了类型注释,GHC会向您大声说'runConduit $ ...'的结果不是'IO [()]',而是'IO [IO()]'。 – Zeta

回答

6

管道的结果是IO()在单子的列表,而不是单一IO()

Prelude Conduit> :t runConduit $ yieldMany [1..10] .| mapC show .| mapC print .| sinkList 
runConduit $ yieldMany [1..10] .| mapC show .| mapC print .| sinkList 
    :: Monad m => m [IO()] 

即使您设置mIO,你最终IO [IO()]作为结果,不得到显示,因为[IO()]没有Show实例。您可以修复,如果您添加>>= sequence_

(runConduit $ yieldMany [1..10] .| mapC show .| mapC print .| sinkList) >>= sequence_ 

然而,真正的问题是,你使用mapC print,而不是mapMC print

Prelude Conduit> :t mapC 
mapC :: Monad m => (a -> b) -> Conduit a m b 
Prelude Conduit> :t mapMC 
mapMC :: Monad m => (a -> m b) -> Conduit a m b 

如果使用mapC print,你结束了Conduit a m (IO())。如果您使用mapMC print,则最终结果为Conduit a IO()。后者设置mIO,第一个没有。

所以使用正确的组合子的一元函数:

runConduit $ yieldMany [1..10] .| mapC show .| mapMC print .| sinkNull 
--            ^

此外,检查的it类型的GHCI如果你没有得到预期的结果。