抱歉,我刚开始研究反应式香蕉和玻璃钢。
reactive-banana的作者根据我的建议制作了this示例,其中他创建了一个可以增加和减少的计数器。他使用accumE函数来累积事件。我想我能够在一定程度上理解事件类型,并能够用它测试相当多的东西,但随后我记起还有行为。我研究过它,但似乎该行为旨在用于类似的情况;修改现有变量,就像accumE对事件所做的那样。
行为意味着什么,它的用例是什么?
发布于 2011-06-30 20:43:51
从语义上讲,你有
Behavior a = Time -> a也就是说,Behavior a是随时间变化的a类型的值。通常,您对Behavior a何时会更改一无所知,因此对于单击按钮更新文本字段来说,这是一个相当糟糕的选择。也就是说,很容易获得一个行为来表示反例子中数字的当前值。只需在事件流上使用stepper,或者以相同的方式从头开始构建它,只是使用accumB而不是accumE。
通常,您连接到输入和输出的内容将始终是Events,因此Behavior在内部用于中间结果。
假设在给定的示例中,您希望添加一个记住当前值的新按钮,就像简单计算器上的memory函数一样。首先,为记住的值添加一个内存按钮和一个文本字段:
bmem <- button f [text := "Remember"]
memory <- staticText f []您需要能够在任何时候请求当前值,因此在您的网络中,您需要添加一个行为来表示它。
let currentVal = stepper 0 counter然后,您可以挂接事件,并在每次按下记忆按钮时使用apply读取行为的值,并生成具有该值序列的事件。
emem <- event0 bmem command
let memoryE = apply (const <$> currentVal) emem最后,将这个新事件连接到输出
sink memory [text :== ("", show <$> memoryE)]如果你想在内部使用内存,那么你也需要为它的当前值设置一个Behavior…但是由于我们只使用它来连接到输出,所以我们现在只需要一个事件。
这有帮助吗?
发布于 2011-07-01 08:30:01
我同意Ankur而不是Chris的观点:文本框是一种随时间变化的值,因此自然希望成为一种行为,而不是事件。Chris给出的事件选择不太自然的原因是实现问题,因此(如果准确的话)是响应式香蕉实现的不幸工件。我更希望看到实现得到改进,而不是不自然地使用范例。
除了语义匹配之外,选择Behavior而不是Event也是非常有用的。例如,您可以使用Applicative操作(例如,liftA2)将随时间变化的文本框值与其他随时间变化的值(行为)组合在一起。
发布于 2011-07-04 22:55:23
我是图书馆的作者。:-)
显然,Chris Smith可以读心术,因为他准确地描述了我在想什么。:-)
但是Conal和Arthur也有一个观点。从概念上讲,计数器是随时间变化的值,而不是事件发生的序列。因此,将其视为Behavior会更合适。
不幸的是,行为没有任何关于何时会改变的信息,这些都是“仅限投票”的。现在,我可以尝试实现各种聪明的方案来最小化轮询,从而允许有效地更新GUI元素。(Conal在original paper中也做了类似的事情。)但我采用了“没有魔法”的哲学:图书馆用户应该自己负责通过事件来管理更新。
我目前设想的解决方案是提供除Event和Behavior之外的第三种类型,即Reactive (name subject to change),它体现了两者的特性:从概念上讲,它是一个随时间变化的值,但它也带有一个通知更改的事件。一种可能的实现是
type Reactive a = (a,Event a)
changes :: Reactive a -> Event a
changes (_, e) = e
value :: Reactive a -> Behavior a
value (x, e) = stepper x e毫不奇怪,这正是sink所期望的类型。这将包含在反应式香蕉库的未来版本中。
编辑:我已经发布了reactive-banana version 0.4,它包含了新的类型,现在被称为Discrete。
https://stackoverflow.com/questions/6534429
复制相似问题