[英]What is the connection between Iteratees and FRP?
It seems to me that there is a strong connection between the two ideas. 在我看来,这两个想法之间存在着密切的联系。 My guess is that FRP could be implemented in terms of Iteratees if there would be a way to express arbitrary graphs with Iteratees.
我的猜测是,如果有一种方法可以用迭代器表示任意图形,那么FRP可以用Iteratees来实现。 But afaik they only support chain-like structures.
但是afaik他们只支持链式结构。
Could someone shed some light on this? 有人可以对此有所了解吗?
It's the other way around. 这是相反的方式。 There is a strong connection between AFRP and stream processing.
AFRP和流处理之间存在很强的联系。 In fact AFRP is a form of stream processing, and you can use the idiom to implement something very similar to pipes:
事实上,AFRP 是流处理的一种形式,你可以使用这个习惯来实现与管道非常相似的东西:
data Pipe m a b =
Pipe {
cleanup :: m (),
feed :: [a] -> m (Maybe [b], Pipe m a b)
}
That's an extension of wire categories as found in Netwire. 这是Netwire中的电线类别的扩展。 It receives the next chunk of input and returns Nothing when it stops producing.
它接收下一个输入块并在停止生成时返回Nothing。 Using this a file reader would have the following type:
使用此文件阅读器将具有以下类型:
readFile :: (MonadIO m) => FilePath -> Pipe m a ByteString
Pipe is a family of applicative functors, so to apply a simple function to the stream elements you could just use fmap : Pipe是一系列应用函子,所以要将一个简单的函数应用于流元素,你可以使用fmap :
fmap (B.map toUpper) . readFile
For your convenience it's also a family of profunctors. 为了您的方便,它也是一个系列的教师。
The most interesting feature is that this is a family of Alternative functors. 最有趣的功能是这是一系列替代函子。 That allows you to route streams around and allow multiple stream processors to "try" before giving up.
这允许您路由流并允许多个流处理器在放弃之前“尝试”。 This can be extended to a full-fledged parsing library that can even use some static information for optimization purposes.
这可以扩展到一个完整的解析库,甚至可以使用一些静态信息进行优化。
You can implement a limited form of FRP using stream processors. 您可以使用流处理器实现有限形式的FRP。 For example, using the
pipes
library, you might define a source of events: 例如,使用
pipes
库,您可以定义事件源:
mouseCoordinates :: (Proxy p) => () -> Producer p MouseCoord IO r
... and you might similarly define a graphical handler that takes mouse coordinates and updates a cursor on a canvas: ...您可以类似地定义一个图形处理程序,它接受鼠标坐标并更新画布上的光标:
coordHandler :: (Proxy p) => () -> Consumer p MouseCoord IO r
Then you would hook up the mouse events to the handler using composition: 然后,您将使用组合将鼠标事件连接到处理程序:
>>> runProxy $ mouseCoordinates >-> coordHandler
And it would run just the way you expect. 它会像你期望的那样运行。
Like you said, this works well for a single chain of stages, but what about more arbitrary topologies? 就像你说的那样,这适用于单个连锁阶段,但是更多的任意拓扑呢? Well, it turns out that since the central
Proxy
type of pipes
is a monad transformer, you can model any arbitrary topology just by nesting proxy monad transformers on top of themselves. 好吧,事实证明,由于中央
Proxy
类型的pipes
是monad变换器,你可以通过在它们自己之上嵌套代理monad变换器来建模任何任意拓扑。 For example, here is how you would zip two input streams: 例如,以下是如何压缩两个输入流:
zipD
:: (Monad m, Proxy p1, Proxy p2, Proxy p3)
=> () -> Consumer p1 a (Consumer p2 b (Producer p3 (a, b) m)) r
zipD () = runIdentityP $ hoist (runIdentityP . hoist runIdentityP) $ forever $ do
a <- request () -- Request from the outer Consumer
b <- lift $ request () -- Request from the inner consumer
lift $ lift $ respond (a, b) -- Respond to the Producer
This behaves like a curried function. 这表现得像一个curried函数。 You partially apply it to each input sequentially and you can then run it when it is fully applied.
您可以按顺序将其部分应用于每个输入,然后可以在完全应用它时运行它。
-- 1st application
p1 = runProxyK $ zipD <-< fromListS [1..]
-- 2nd application
p2 = runProxyK $ p2 <-< fromListS [4..6]
-- 3rd application
p3 = runProxy $ printD <-< p3
It runs just the way you expect: 它以您期望的方式运行:
>>> p3
(1, 4)
(2, 5)
(3, 6)
This trick generalizes to any topology. 这个技巧推广到任何拓扑。 You can find a lot more details about this in Control.Proxy.Tutorial in the "Branches, zips, and merges" section.
您可以在“分支,拉链和合并”部分的Control.Proxy.Tutorial中找到有关此内容的更多详细信息。 In particular, you should check out the
fork
combinator it uses as an example, which lets you split a stream into two outputs. 特别是,您应该检查它使用的
fork
组合器作为示例,它允许您将流拆分为两个输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.