Closed roryc89 closed 6 years ago
It's not possible to have blocks of parallel code like that in general because Run
is open-world, and not all effects can be run in parallel and then joined. It's possible to fork
(that's essentially what CHOICE
gives you), but then resuming from a single point after some set of effects have completed always requires consideration. For example, if you run multiple STATE
effects in parallel, how do you join the results? You might have to require a commutative Monoid for the state type then for it to make sense. Likewise with EXCEPT
, how do you recover if one of your forks (or all of them) throws? Do you collect errors, discard errors, etc? You have to handle each case specifically according to the semantics you want, and there's no possible one-size-fits-all solution.
One option is to define a closed-world set of effects that are known to run in parallel with the semantics you want, and lift that into your Run
effects.
newtype MyParEffects a =
MyParEffect (FreeAp (Run (...)) a)
liftParEffects :: forall r a. MyParEffects a -> Run (par :: FProxy MyParEffects | r) a
liftParEffects = Run.lift (SProxy :: SProxy "par")
Your interpreter can than interpret the FreeAp
of all the embedded Run
effects in parallel.
An alternative would be to have only fork
ing as an effect, and then also have some sort of coordination primitive like AVar
s to deal with joins.
Thanks a lot! This is just what we were looking for. I assume this can be closed then?
We have a blocks of program we would like to run in parallel. Is there any way to perform this sort of logic with purescript-run?
I.e.:
Any help would be greatly appreciated. So far we have only been able to interpret the program sequentially.