-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lawful concurrent version #31
Conversation
@safareli How would I optimize some parallel fragment? |
@jdegoes Can you give some example of optimising parallel fragment in |
It's a transformation from |
Yah I get it, but what I asked was actual useful example of optimising parallel fragmen in SeqPar so i have something to test against. |
Current coverage is 98.82% (diff: 98.80%)@@ dev #31 diff @@
=====================================
Files 2 7 +5
Lines 95 170 +75
Methods 0 0
Messages 0 0
Branches 0 0
=====================================
+ Hits 95 168 +73
- Misses 0 2 +2
Partials 0 0
|
For example, compiling an applicative parser & achieving fusion. |
@jdegoes If you have some parallel fragment of type for example: > a = lift2(a => b => `${a}-{b}`, Par.lift(1), Par.lift(2))
Par.Apply(1, Par.Apply(2, Par.Pure(a => bc(ab(a)))))
a :: Par Number String To be able to use it alongside with > b = a.hoistPar(Concurrent.lift)
Par.Apply(Concurrent.Lift(2), Par.Apply(Concurrent.Lift(1), Par.Pure(a => bc(ab(a)))))
b :: Par (Concurrent Number) String now it's valid argument to > c = Concurrent.Par(b)
Concurrent.Par(Par.Apply(Concurrent.Lift(2), Par.Apply(Concurrent.Lift(1), Par.Pure(a => bc(ab(a))))))
c :: Concurrent Number String For now i don't have some special way to optimise Parallel fragments but you can see that it's possible for > d = c.chain(v => Concurrent.lift(3).map(x => `${v}: ${x}`))
// we could also use `lift2` as `ap` is derived from `chain`
Concurrent.Seq(
Seq.Roll(
Concurrent.Par(
Par.Apply(Concurrent.Lift(2), Par.Apply(Concurrent.Lift(1), Par.Pure(a => bc(ab(a)))))
),
a => chain(bc, ab(a))
)
)
d :: Concurrent Number String ... and if you use > e = Concurrent.Par(lift2(a => b => `${a}-{b}`, d.par(), Concurrent.lift(4).par()))
Concurrent.Par(
Par.Apply(// [3]
Concurrent.Seq(
Seq.Roll(
Concurrent.Par(
Par.Apply(Concurrent.Lift(2), Par.Apply(Concurrent.Lift(1), Par.Pure(a => bc(ab(a))))) // [1]
),
a => chain(bc, ab(a))
)
),
Par.Apply(Concurrent.Lift(4), Par.Pure(a => bc(ab(a)))) // [2]
)
)
e :: Concurrent Number String then you can do any optimisation on parts like Main advantage of a :: Concurrent Number String // Might contains Par and Seq
b :: Concurrent Number String // Might contains Par and Seq
Concurrent.Par(lift2(z => x => x + z, a.par(), b.par())) :: Concurrent Number String |
88df432
to
fb2674e
Compare
it's almost done:
|
🎉 💃 As of last commit Par (FreeApplicative) has Just a bit of refactoring is left for it to be merged |
it's easy to move between Seq and Par by just composing from{Seq,Par} and {Seq,Par}.lift ```js // parToSeq :: Par (Concurrent f) a -> Seq (Concurrent f) a const parToSeq = v => Seq.lift(fromPar(v)) // seqToPar :: Seq (Concurrent f) a -> Par (Concurrent f) a const seqToPar = v => Par.lift(fromSeq(v)) ```
complexity of map/ap - O(1), fold - O(n); also fold is stack safe
This is breaking change.
Old implementation was relaying that the target monad was not lawful.
initially i have ported old version of haskell-free-concurrent by @srijs, because I did not quite understood the lenses operators used in the latest version and the latest version was a bit hard to understand. But recently I did another try to understand it and here is the result.
What has changed
Now we have
Concurrent
structure which is a Monad, it holdsPar
allel orSeq
uential computations which are itself holding Concurrent computations.When operating on Concurrent structures it's behaving as Sequential. but in cases you want Parallel behaviour you can call
.par()
on it and it will returnPar
object which is only Applicative. then you can move back toConcurrent
usingConcurrent.Par
.here is visual version:

Interpreter
Currently Interpreter looks like this:
TODO
interpret
(usefold
s)ChainRec
graft
,hoist
retract
Par
structures overflow stack on fold and if yes optimise it using tail recursion.Seq
implementation detail so that user will only deal withConcurrent
andPar
asConcurrent
is delegating actions to underlyingSeq
Related to #27