Как удалить повторяющиеся события в реактивном банане

В реактивном банане у меня есть поток событий, который создает серию чисел, некоторые из которых повторяются несколько раз подряд (меня не интересуют все дубликаты, а только последовательные дубликаты). Как я могу изменить этот поток событий, чтобы он содержал только непоследовательные дубликаты?

Я попытался использовать изменения, чтобы преобразовать его в поведение, думая, что поведение «изменится» только тогда, когда событие будет новым числом, но вместо этого поведение запускает событие изменения каждый раз, когда получено новое событие ввода.


person Orclev    schedule 03.04.2012    source источник


Ответы (2)


Обратите внимание, что функцию changes следует использовать только для привязки к наборам инструментов GUI и т. п., ее не следует использовать для обычного программирования с событиями и поведением.

Функция, которая подавляет повторяющиеся события, может быть выражена с помощью комбинаторов mapAccum и filterJust следующим образом.

skipEqual :: Eq a => Event t a -> Event t a
skipEqual = filterJust . fst . mapAccum Nothing . fmap f
    where
    f y (Just x) = if x == y then (Nothing,Just x) else (Just y,Just y)
    f y Nothing  = (Just y, Just y)

test = interpretModel skipEqual $ map (:[]) [1 :: Int,1,2,3,3,2]

Запуск test дает

*Main> test
[[1],[],[2],[3],[],[2]]

по желанию.

Другими словами, вы можете просто представить Event как список вхождений, а затем применить к нему свои любимые комбинаторы «список».

person Heinrich Apfelmus    schedule 03.04.2012
comment
О, почему я не подумал об этом?! Я удалил уродливую реализацию из своего ответа в пользу этого. - person ehird; 03.04.2012
comment
если вы не должны использовать изменения, как вы делаете что-то значимое с поведением? - person Orclev; 04.04.2012
comment
@Orclev: вы можете apply вести себя с событиями. Для этого используются операторы <@> и <@. Кроме того, вы можете использовать взаимную рекурсию между поведениями и событиями. - person Heinrich Apfelmus; 04.04.2012

Ну, changes ничего не превращает в Behavior; он просто позволяет вам наблюдать за изменениями Behavior в NetworkDescription, чтобы вы могли приклеить их к внешним фреймворкам. поведение changes описывается как changes (stepper x e)return (calm e), поэтому передача события туда и обратно через stepper и changes не будет иметь никакого эффекта, кроме calm (который просто отбрасывает все одновременные вхождения, кроме первого).

Полезно иметь комбинатор для отбрасывания вхождений, которые не изменяют значение, и я думаю, что в некоторых других фреймворках FRP он встроен. Но вы можете довольно легко написать свой собственный, как показывает ответ Генриха.

person ehird    schedule 03.04.2012