public static Process <T2> SelectMany <T1, T2>(this Process <T1> m, Func <T1, Process <T2> > f) { return(m.Match( halt: e => new Halt <T2>(e), emit: (h, t) => Try(() => f(h)).Concat(() => t.SelectMany(f)), await: (req, recv) => Await <T2> .Create(req, recv.AndThen(p => p.SelectMany(f))), cont: cw => new Cont <T2>(cw.Select(p => p.SelectMany(f))), eval: (effect, next) => new Eval <T2>(effect, next.SelectMany(f)))); }
public static Process <Unit> Delay(int milliseconds) { return(Await <Unit> .Create(() => { Thread.Sleep(milliseconds); return Unit.Only; }, either => either.Match( left: ex => new Halt <Unit>(ex), right: i => new Halt <Unit>(End.Only)))); }
private static Process <T> BufferHelper <TState, T>(TState buffer, Func <TState> @new, Action <T, TState> add, Func <TState, bool> ready, Func <TState, T> flush) { return(Await <T> .Create(() => default(T), either => either.Match( left: e => new Halt <T>(e), right: i => { add(i, buffer); return ready(buffer) ? new Emit <T>(flush(buffer)).Concat(() => BufferHelper(@new(), @new, add, ready, flush)) : new Cont <T>(() => BufferHelper(buffer, @new, add, ready, flush)); }))); }
private static Process <IEither <T1, T2> > HandleBranch <T1, T2>(object l, Func <IEither <Exception, object>, Process <T1> > recvl, Func <IEither <Exception, object>, Process <T2> > recvr, bool isLeft) { Process <IEither <T1, T2> > retval; var pair = (Tuple <object, Func <object> >)l; if (isLeft) { retval = Wye(recvl(pair.Item1.AsRight <Exception, object>()), Await <T2> .Create(pair.Item2, recvr)); } else { retval = Wye(Await <T1> .Create(pair.Item2, recvl), recvr(pair.Item1.AsRight <Exception, object>())); } return(retval); }
public static Process <IEither <T1, T2> > Wye <T1, T2>(Process <T1> p1, Process <T2> p2) { var random = new Random(); if (random.Next() % 2 == 0) { return(p1.Match( halt: e => new Halt <IEither <T1, T2> >(e), emit: (h, t) => new Emit <IEither <T1, T2> >(h.AsLeft <T1, T2>(), Wye(t, p2)), cont: cw => new Cont <IEither <T1, T2> >(cw.Select(p => Wye(p, p2))), eval: (effect, next) => new Eval <IEither <T1, T2> >(effect, Wye(next, p2)), await: (reql, recvl) => p2.Match <Process <IEither <T1, T2> > >( halt: e => new Halt <IEither <T1, T2> >(e), emit: (h, t) => new Emit <IEither <T1, T2> >(h.AsRight <T1, T2>(), Wye(Await <T1> .Create(reql, recvl), t)), cont: cw => new Cont <IEither <T1, T2> >(cw.Select(p => Wye(p1, p))), eval: (effect, next) => new Eval <IEither <T1, T2> >(effect, Wye(p1, next)), await: (reqr, recvr) => Await <IEither <T1, T2> > .Create(WhenEither(reql, reqr), x => x.Match( left: e => new Halt <IEither <T1, T2> >(e), right: either => either.Match( left: l => HandleBranch(l, recvl, recvr, true), right: r => HandleBranch(r, recvl, recvr, false))))))); } else { return(p2.Match( halt: e => new Halt <IEither <T1, T2> >(e), emit: (h, t) => new Emit <IEither <T1, T2> >(h.AsRight <T1, T2>(), Wye(p1, t)), cont: cw => new Cont <IEither <T1, T2> >(cw.Select(p => Wye(p1, p))), eval: (effect, next) => new Eval <IEither <T1, T2> >(effect, Wye(p1, next)), await: (reqr, recvr) => p1.Match <Process <IEither <T1, T2> > >( halt: e => new Halt <IEither <T1, T2> >(e), emit: (h, t) => new Emit <IEither <T1, T2> >(h.AsLeft <T1, T2>(), Wye(t, p2)), cont: cw => new Cont <IEither <T1, T2> >(cw.Select(p => Wye(p, p2))), eval: (effect, next) => new Eval <IEither <T1, T2> >(effect, Wye(next, p2)), await: (reql, recvl) => Await <IEither <T1, T2> > .Create(WhenEither(reql, reqr), x => x.Match( left: e => new Halt <IEither <T1, T2> >(e), right: either => either.Match( left: l => HandleBranch(l, recvl, recvr, true), right: r => HandleBranch(r, recvl, recvr, false))))))); } }
public static Process <T> AwaitAndEmit <T>(Func <T> effect) { return(Await <T> .Create(effect, result => result.Match <Process <T> >( left: ex => new Halt <T>(ex), right: ti => new Emit <T>(ti)))); }
public static Process <T> While <T>(this Process <T> p, Func <bool> predicate) { return(Await <T> .Create(predicate, either => either.Match( left: e => new Halt <T>(e), right: b => b ? p.Concat(() => p.While(predicate)) : new Halt <T>(End.Only)))); }