默认情况下,管道是基于拉的。这是由于实现的操作>->
符是他的拉动类别+>>
的重要操作符。bind
我的理解是,这意味着如果你有类似producer >-> consumer
的代码,首先会调用消费者的主体,然后一旦等待数据,就会调用生产者。
我在这里pipes
的文档中看到,您可以使用代码将基于拉的管道转换为基于推的管道。这意味着相反(如果我错了,请纠正我)在上面的代码中,生产者首先运行,产生一个值,然后消费者尝试消费。这似乎真的很有用,我想知道该怎么做。(reflect .)
Pipes.Core
producer >-> consumer
我在这里的讨论中也看到,没有基于推送的对应物,>->
因为它很容易扭转任何管道(我假设使用反射?),但我真的不知道如何去做或找到任何例子。
这是我尝试过的一些代码:
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))