haskell - 了解 `conduit` 输出

标签 haskell

使用管道,给定:

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,值将是打印出来。

请解释这个输出。

最佳答案

管道的结果是 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 实例。如果添加 >>= 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,而第一个则没有。

所以对单子(monad)函数使用正确的组合器:

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

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

关于haskell - 了解 `conduit` 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44327727/

相关文章:

haskell - 在 Haskell 中使用递归数据类型创建向后列表

haskell - Rank 2 多态性的实际应用?

haskell - 从文本输入更新记录

Haskell Char 和 unicode 代理

haskell - 编译时的顶级表达式评估

http - 如何使用 Network.HTTP.receiveHTTP 在 Haskell 中编写一个简单的 HTTP 服务器

haskell - 仅适用于一种类型的一个构造函数的函数

haskell - 获取匹配长度(秒差距)

haskell - Haskell 中的非详尽模式匹配

haskell - Scheme中没有显式突变的向后延续的最简单示例