Что не так с моим "событием суммы" в реактивном банане?

Я изучаю реактивный банан и собираюсь использовать его в приложении на стороне сервера. У меня есть некоторый опыт работы с RxJ, поэтому я привык комбинировать события с разными комбинаторами. Итак, я начал с простых примеров комбинатора событий. Я попытался сделать простой пример реактивного банана, который бы объединил два целочисленных события в событие суммы. Я понимаю, что для того, чтобы объединить значения из разных событий, я должен сначала превратить их в Поведения, затем выполнить комбинацию и, наконец, превратить это в новое событие. Вот как я это сделал:

-- Behaviors from Events e1, e2
let b1 = stepper 0 e1 :: Behavior Int
let b2 = stepper 0 e2 :: Behavior Int

-- Sum Behavior
let sumB = (+) <$> b1 <*> b2
-- Back to Event
let sumE = sumB <@ (e1 `union` e2)

Полный пример запуска можно найти в Gist 1594917.

Проблема здесь заключается в том, что хотя событие sumE правильно запускается, когда в одном из событий (e1, e2) появляется новое значение, оно содержит устаревшее значение. Это, по-видимому, связано с тем, как работает степпер (значение поведения меняется "незначительно после" возникновения события). Я попытался заменить Поведение на Дискретное, с тем же результатом.

Есть ли простой способ заставить этот вид комбинаторов событий работать правильно?

1 ответ

Решение

Ваш диагноз точно верный. Вот два варианта: вы можете вернуться к событию с дискретного через changesИли вы можете создавать накапливающиеся события.

Работать с Discrete, вероятно, проще (и я бы порекомендовал). Просто делать

-- Discretes from Events e1, e2
let d1 = stepperD 0 e1 :: Discrete Int
let d2 = stepperD 0 e2 :: Discrete Int

-- Sum Discrete
let sumD = (+) <$> d1 <*> d2
-- Back to Event
let sumE = changes sumD

Сейчас sumE всегда будет обновляться, когда e1 или же e2 изменения.

Альтернатива использует только События, преобразовывая входящие события в функции накопления. Звучит сложно, но код довольно прост.

--convert each input into an accumulating tuple
let e1' = (\l (_,r) -> (l,r)) <$> e1
let e2' = (\r (l,_) -> (l,r)) <$> e2

let sumE = uncurry (+) <$> accumE (0,0) (e1' `union` e2')
Другие вопросы по тегам