Pregunta

Let's say I have

x :: Event t (A,B)

I can get the first component of it:

fst <$> x :: Event t A

However, this event will fire even when the first component doesn't change. I want to avoid that, because it would trigger an expensive recomputation.

A is an instance of Eq, so I want to be able to remove the successive events where the first component is not changed compared to its last value.

Ideally, I'd like a function

filterDups :: Eq a => Event t a -> Event t a

which would do that without resorting to the Moment monad. Is it possible? Or what's the best way to do this?

¿Fue útil?

Solución

You have to remember information about the history of the event to do what you want. As other answers have already mentioned, you can use accumE for that purpose. Here a succinct definition:

unique :: Eq a => Event t a -> Event t a
unique = filterJust . accumE Nothing
       . fmap (\a acc -> if Just a == acc then Nothing else Just a)

Otros consejos

I've never used reactive-banana, and haven't tested this, so beware. Nevertheless, here's one idea that at the very least typechecks. We'll use accumE to remember something about past events.

notice x (old, new) = (new, Just x)

changed (Just old, Just new) = guard (old /= new) >> return new
changed (_, new) = new

justChanges :: Eq a => Event t a -> Event t a
justChanges e = filterJust $ changed <$> accumE (Nothing, Nothing) (notice <$> e)

This solution uses (or abuses) the fact that the stepper function updates the Behavior "slightly after" the Event, see the comment in the docs.

First create a Behavior based on the Event, you have to find a suitable first value for the Behavior in your solution, for simplicity I am assuming that the first element of your pair is an Int:

x :: Event t (Int, b)

firstB :: Behavior t Int
firstB = stepper 0 $ fst <$> x

Then you can use the filterApply function:

filterDups e = filterApply (firstNotEq <$> firstB) e
    where firstNotEq old (new, _) = new /= old
          firstB                  = stepper 0 $ fst <$> e

Take a look at this gist for a simple example using the Threepenny GUI.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top