Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to transform events with an IO function?

Let's say I have

e1 :: Event t A
f  :: A -> IO B

I want to create

e2 :: Event t B

which is triggered by e1, and whose values are determined by executing f on the value of e1 at the time of the event occurrence.

I see two potential ways to do this, via dynamic event switching and using handlers, but they both look too complicated for such a simple thing.

What is the proper way to do this?

like image 673
Roman Cheplyaka Avatar asked Oct 22 '22 07:10

Roman Cheplyaka


1 Answers

Since the function f has a side effect, this is actually not a simple thing to do. The main reason is that the order of side effects is not well-defined when there are multiple simultaneous events. More generally, I was unable to conceive a good semantics for dealing with IO actions in events. Consequently, reactive-banana does not provide a pure combinator for this situation.

If you want to do this anyway, you have to use a more elaborate mechanism that also determines the order of side effects. For instance, you can use reactimate and write a combinator

mapIO :: Frameworks t => (a -> IO b) -> Event t a -> Moment t (Event t b)
mapIO f e1 = do
    (e2, fire2) <- liftIO newAddHandler
    reactimate $ (\x -> f x >>= fire2) <$> e1
    fromAddHandler e2

However, note that this may give unexpected results as the result event e2 is no longer simultaneous with the input event e1. For instance, behaviors may have changed and other side effects may have been executed.

like image 181
Heinrich Apfelmus Avatar answered Nov 01 '22 15:11

Heinrich Apfelmus