默认管道是基于拉的。这是由于运营商>->
,这是通过+>>
实现的,这是bind
运营商针对他的拉动类别。我的理解是,这意味着如果你有代码producer >-> consumer
,消费者的身体将被首先调用,然后一旦它等待数据,生产者将被调用。如何将基于拉的管道变为基于推拉的管道?
我见过的pipes
文档here,你可以使用代码(reflect .)
从Pipes.Core
把一个基于拉管道进入基于推送管英寸这意味着相反(如果我错了,请纠正我)在producer >-> consumer
以上的代码中,生产者首先运行,生成一个值,然后消费者尝试消费。这似乎很有用,我想知道如何去做。
我也看到讨论here没有基于推送对口>->
因为它很容易把任何管道周围(我假设有反映?),但我真的不能弄清楚如何做到这一点或找到任何例子。
下面是一些代码,我已经尝试:
stdin :: Producer String IO r
stdin = forever $ do
lift $ putStrLn "stdin"
str <- lift getLine
yield str
countLetters :: Consumer String IO r
countLetters = forever $ do
lift $ putStrLn "countLetters"
str <- await
lift . putStrLn . show . length $ str
-- this works in pull mode
runEffect (stdin >-> countLetters)
-- equivalent to above, works
runEffect ((\() -> stdin) +>> countLetters)
-- push based operator, doesn't do what I hoped
runEffect (stdin >>~ (\_ -> countLetters))
-- does not compile
runEffect (countLetters >>~ (\() -> stdin))