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 <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))))))); } }