<div dir="ltr"><div><div><div><div>Interresting!<br></div>Could you make your type "Process" an instance of MonadParallel?<br><a href="https://hackage.haskell.org/package/monad-parallel-0.7.1.2/docs/Control-Monad-Parallel.html">https://hackage.haskell.org/package/monad-parallel-0.7.1.2/docs/Control-Monad-Parallel.html</a><br><br></div>This way you could use Control.Monad.Parallel.sequence instead of processParallel.<br><br></div>But as you can see, processParallel, albeit making the computations in parallel, as to wait for all processes to finish.<br></div>In my case, I want to be able to cancel some of the remaining events: so Control.Monad.Parallel doesn't seem to be a good fit.<br><div><div><div><br><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 8, 2014 at 3:53 AM, David Sorokin <span dir="ltr"><<a href="mailto:david.sorokin@gmail.com" target="_blank">david.sorokin@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div>Corentin,</div><div><br></div><div>As far as I understand, it is similar in implementation to what I have in my simulation library Aivika [1]. Please correct me if I am wrong:</div><div><br></div><div><div>-- | Execute the specified computations in parallel within</div><div>-- the current computation and return their results. The cancellation</div><div>-- of any of the nested computations affects the current computation.</div><div>-- The exception raised in any of the nested computations is propagated</div><div>-- to the current computation as well.</div></div><div>processParallel :: [Process a] -> Process [a]</div><div><br></div><div>It looks like that my Process type is an equivalent of your type Event in some sense. Only here we would have to cancel (or, interrupt in your terms) all other Process computations right after we receive a final result.</div><div><br></div><div>So, if it is true then it is possible to write a new function based on the stated above so that it would be similar to the ShortcutEvents function:</div><div><br></div><div>shortcutProcesses: [Process a] -> ([Maybe a] -> Maybe b) -> Process b</div><div><br></div><div>Probably, I should add such a function to my library too.</div><div><br></div><div>Thanks,</div><div>David </div><div><br></div><div>[1] <a href="http://hackage.haskell.org/package/aivika" target="_blank">http://hackage.haskell.org/package/aivika</a></div><div><br></div><br><div><div>08 сент. 2014 г., в 0:23, Corentin Dupont <<a href="mailto:corentin.dupont@gmail.com" target="_blank">corentin.dupont@gmail.com</a>> написал(а):</div><div><div class="h5"><br><blockquote type="cite"><div dir="ltr"><div><div><div><div>Hi guys,<br></div>thanks for the nice answers!<br></div>I'll give you a little bit more context: I'm designing an event engine. I have instances for Applicative, Alternative, Monad, MonadPlus.<br></div>It's like that:<br></div><div><div><br><br><span style="font-family:courier new,monospace">-- | Composable events<br>data Event a where<br>   SumEvent       :: Event a -> Event a -> Event a            -- The first event to fire will be returned.<br>   AppEvent       :: Event (a -> b) -> Event a -> Event b     -- Both events should fire, and then the result is returned.<br>   PureEvent      :: a -> Event a                             -- Create a fake event. The result is useable with no delay.<br>   EmptyEvent     :: Event a                                  -- An event that is never fired.<br>   BindEvent      :: Event a -> (a -> Event b) -> Event b     -- The first event should fire, then a second event is created using the result.<br>   BaseEvent      :: BaseEvent a -> Event a                   -- Embed a base event.<br>   ShortcutEvents :: [Event a] -> ([Maybe a] -> Maybe b) -> Event b -- The function is called each time an event fires, as soon as the result can be computed </span><span style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">from the available data,</span> it is returned, dismissing the events that haven't fired yet.</span><br><span style="font-family:courier new,monospace"><br><br>instance Functor Event where<br>   fmap f a = pure f <*> a<br><br>instance Applicative Event where<br>   pure = PureEvent<br>   (<*>) = AppEvent<br><br>instance Alternative Event where<br>   (<|>) = SumEvent<br>   empty = EmptyEvent<br><br>instance Monad Event where<br>   (>>=) = BindEvent<br>   return = PureEvent<br><br>instance MonadPlus Event where<br>   mplus = SumEvent<br>   mzero = EmptyEvent<br><br></span><br>The Applicative instance is good if you have two events and you want 
both of them to fire ("and"). The Alternative instance is good if you have two events and you need only one to fire ("or").<br>But 
what if you have several events, but you need only a part of them to 
fire in order to construct a final result? Say you have 10 events, but the 5 first to fire will give you enough data to construct a result.<br>You cannot do that with 
Applicative/Alternative because with Applicative, you need *all* events 
results, with Alternative you need *only one*.<br><br></div><div>That's why I added this primitive "<span style="font-family:courier new,monospace">ShortcutEvents"<span style="font-family:arial,helvetica,sans-serif"> in my DSL, but I'm not convinced by it. So my questions are:<br></span></span></div><div><span style="font-family:arial,helvetica,sans-serif">1. is ShortcutEvents expressible in term of </span>Applicative/Alternative/Monad/MonadPlus?<br></div><div>2. if not is their a well known typeclass that covers this case?<br></div><div>3. if not is their a better way to write it? I especially don't like the list of Event, I'd prefer a more generic writing. What if I want a structure containing the events, instead of a list? What if I want event of various types (say a pair<span style="font-family:courier new,monospace"> (Event a, Event b)</span> for example)?<br></div><div><br><br></div><div>Note that I'm not working with streams of events (like in traditional FRP frameworks): just with single events (the "BaseEvents") that I want to combine with each other. Those "BaseEvents" will fire only once. The final result of the combination of events will trigger a callback.<br><br></div><div>Cheers,<br></div><div>Corentin<br></div><br></div></div>
</blockquote></div></div></div><br></div></blockquote></div><br></div></div></div></div></div></div></div>