Haskell 理解“导管”输出
使用导管,给定:Haskell 理解“导管”输出,haskell,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 sh
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]
流,将打印每个元素的字符串
,即显示
,值
请解释此输出。导管的结果是单子中的
IO()
列表,而不是单个IO()
:
即使您将m
设置为IO
,您最终也会得到IO[IO()]
,结果不会显示,因为[IO()]
没有Show
实例。如果添加>>=序列
,则可以修复此问题:
(runConduit $ yieldMany [1..10] .| mapC show .| mapC print .| sinkList) >>= sequence_
但是,真正的问题是使用mapC打印
而不是mapMC打印
:
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打印
,则最终会得到导管a m(IO())
。如果使用mapMC打印
,则最终会得到导管a IO()
。后者将m
设置为IO
,前者不设置
因此,对一元函数使用正确的组合符:
runConduit $ yieldMany [1..10] .| mapC show .| mapMC print .| sinkNull
-- ^
此外,如果没有得到预期的结果,请检查GHCi中的
it
类型。IIRC,您在最近的CR问题中遇到了类似的问题。遇到此类问题时,请使用带有类型批注的适当源文件。您经常会注意到,当您使用IO
时,GHCi的工作原理有点不同。如果您添加类型批注,GHC将对您大喊大叫,runconductor$…
的结果不是IO[()]
,而是IO[IO()]
。
runConduit $ yieldMany [1..10] .| mapC show .| mapMC print .| sinkNull
-- ^