2012-04-03 8 views
7

In reactive-banana habe ich einen Event-Stream, der eine Reihe von Zahlen erzeugt, von denen einige sich mehrmals hintereinander wiederholen (ich bin nicht mit allen Duplikaten beschäftigt, nur sequentielle Duplikate). Wie kann ich diesen Ereignisdatenstrom so ändern, dass er nur nicht sequenzielle Duplikate enthält?Wie entferne ich wiederkehrende Ereignisse in reactive-banana?

Ich versuchte mithilfe von Änderungen, es in ein Verhalten zu konvertieren, das das Verhalten nur ändern würde, wenn das Ereignis eine neue Zahl war, aber das Verhalten löst jedes Mal ein Änderungsereignis aus, wenn ein neues Eingabeereignis empfangen wird.

Antwort

6

Beachten Sie, dass die changes Funktion sollte nur für die Bindung an GUI-Toolkits und dergleichen verwendet werden, sollte es nicht für regelmäßige Programmierung mit Ereignissen und Verhaltensweisen verwendet werden.

Eine Funktion, die doppelten Ereignisvorkommen unterdrückt kann in Bezug auf die mapAccum und filterJust combinators ausgedrückt werden als

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 gibt Rennen folgt

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

nach Wunsch.

Mit anderen Worten, Sie können sich einfach Event als eine Liste von Vorkommen vorstellen und dann Ihre geliebten "Listen" -Kombinatoren darauf anwenden.

+0

Oh, warum habe ich nicht daran gedacht ?! Ich habe die hässliche Implementierung aus meiner Antwort zugunsten dieses entfernt. – ehird

+1

Wenn Sie keine Änderungen verwenden sollten, wie machen Sie etwas Sinnvolles mit einem Verhalten? – Orclev

+0

@Orclev: Sie können Verhalten auf Ereignisse anwenden. Die '<@>' und '<@' Operatoren werden dafür verwendet. Außerdem können Sie die gegenseitige Rekursion zwischen Verhalten und Ereignissen verwenden. –

0

Nun, changes macht nichts zu einem Behavior; es lässt Sie einfach beobachten die Änderungen eines Behavior in NetworkDescription, so dass Sie es an externe Frameworks kleben können. Die behaviour of changes wird als changes (stepper x e)return (calm e) beschrieben, so dass das Rundum-Auslösen eines Ereignisses über stepper und changes keinen anderen Effekt als calm hat (was einfach alle simultanen Vorkommnisse verwirft, aber das erste).

Es ist nützlich, einen Kombinator zu haben, um Vorkommnisse zu verwerfen, die den Wert nicht ändern, und ich denke, einige andere FRP-Frameworks haben einen eingebauten. Aber Sie können Ihre eigenen ziemlich leicht schreiben, wie Heinrichs Antwort zeigt.