2017-06-02 88 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如果你沒有得到預期的結果。