理解`管道`输出

时间:2017-06-02 11:23:37

标签: haskell

使用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,都会打印出来。

请解释此输出。

1 个答案:

答案 0 :(得分:6)

管道的结果是monad中的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 ()]

即使您将m设置为IO,结果也会导致IO [IO ()],因为[IO ()]没有{Show,因此无法显示{1}}实例。如果您添加>>= 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 ()。后者将m设置为IO,第一个不设置。{/ p>

所以使用正确的组合子来实现monadic函数:

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

另外,如果你没有得到预期的结果,请检查GHCi中it的类型。