Подтвердить что ты не робот

Поведение в реакционно-банановой

Простите меня, я только начинаю изучать реактивно-банановые и FRP.

Автор реактивного банана сделал этот пример по моему предложению, в котором он создает счетчик, который можно увеличить и уменьшить. Он использует функцию accE, которая накапливает события. Я думаю, что мне удалось несколько разобрать тип события, и я смог проверить с ним несколько вещей, но потом я вспомнил, что есть также Поведение. Я просмотрел его, но похоже, что поведение должно использоваться в подобных ситуациях; для изменения существующей переменной, подобно тому, как это происходит с событиями.

Что означает поведение, и каковы его варианты использования?

4b9b3361

Ответ 1

Семантически, вы

Behavior a = Time -> a

То есть, Behavior a - это значение типа a, которое изменяется со временем. В общем, вы ничего не знаете о том, когда изменится Behavior a, поэтому он окажется довольно плохим выбором для обновления текстового поля одним нажатием кнопки. Тем не менее, было бы легко получить поведение, которое выражает текущее значение числа в примере счетчика. Просто используйте stepper в потоке событий или, альтернативно, создайте его с нуля таким же образом, за исключением использования accumB вместо accumE.

Как правило, все, что вы подключаете к вводу и выводу, всегда будет Event s, поэтому Behavior используется для промежуточных результатов.

Предположим, что в данном примере вы хотите добавить новую кнопку, которая запоминает текущее значение, например функцию памяти на простых калькуляторах. Вы начнете с добавления кнопки памяти и текстового поля для запоминаемого значения:

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 для его текущего значения... но поскольку мы используем его только для подключения к выходу, нам нужно только событие на данный момент.

Помогает ли это?

Ответ 2

Я согласен с Ankur, а не с Крисом: текстовое поле является значением с течением времени и поэтому естественно хочет быть поведением, а не событием. Причины, которые Крис дает для менее естественного выбора события, - это проблемы реализации и, следовательно, (если они точны) неудачный артефакт реализации реактивного банана. Я бы предпочел, чтобы реализация была улучшена, чем парадигма, используемая неестественно.

Помимо семантической подгонки, прагматически очень полезно выбрать Behavior над Event. Вы можете, например, использовать операции Applicative (например, liftA2), чтобы комбинировать изменяющееся во времени значение текстового поля с другими изменяющимися во времени значениями (поведением).

Ответ 3

В целом, поведение - это значение, которое изменяется в течение определенного периода времени. Это непрерывное значение, когда события являются дискретными значениями. В случае Поведения всегда присутствует значение. Например: текст в текстовом поле - это поведение, так как текст может меняться в течение определенного периода времени, но будет текущее значение, где в качестве штриха клавиатуры в событии, поскольку вы не можете запросить ход клавиатуры для своего "текущего", значение.

Ответ 4

Говорящий автор библиотеки.: -)

Видимо, Крис Смит может читать мысли, потому что он точно описывает то, что я думаю.: -)

Но Конус и Артур тоже имеют смысл. Понятно, что счетчик - это значение, которое меняется во времени, а не последовательность событий. Таким образом, думать об этом как Behavior было бы более подходящим.

К сожалению, поведение не содержит никакой информации о том, когда они будут меняться, "опрос". Теперь я могу попытаться реализовать различные умные схемы, которые минимизируют опрос и, таким образом, позволят эффективные обновления элементов GUI. (Конал делает что-то подобное в оригинальной бумаге.) Но я принял философию "без магии": пользователь библиотеки будет нести ответственность за управление обновления через сами события.

Решением, которое я в настоящее время представляю, является предоставление третьего типа, кроме Event и Behavior, а именно Reactive (имя может быть изменено), которое воплощает в себе качества обоих: концептуально это значение, которое изменяется во времени, но он также поставляется с событием, которое уведомляет об изменениях. Одна из возможных реализаций -

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. Это будет включено в будущую версию библиотеки реактивного банана.

EDIT: я выпустил реактивно-банановый версия 0.4, который включает новый тип, который теперь называется Discrete.