public TryOptionAsync <B> Apply(TryOptionAsync <Func <A, B> > fab, TryOptionAsync <A> fa) => async() => { var f = fab.Try(); var a = fa.Try(); await Task.WhenAll(f, a); var rf = await f; if (rf.IsFaulted) { return(new OptionalResult <B>(rf.Exception)); } if (rf.IsFaultedOrNone) { return(OptionalResult <B> .None); } var ra = await a; if (ra.IsFaulted) { return(new OptionalResult <B>(ra.Exception)); } if (ra.IsFaultedOrNone) { return(OptionalResult <B> .None); } return(new OptionalResult <B>(rf.Value.Value(ra.Value.Value))); };
public static TryAsync <TryOptionAsync <B> > Traverse <A, B>(this TryOptionAsync <TryAsync <A> > ma, Func <A, B> f) { return(ToTry(() => Go(ma, f))); async Task <Result <TryOptionAsync <B> > > Go(TryOptionAsync <TryAsync <A> > ma, Func <A, B> f) { var ra = await ma.Try().ConfigureAwait(false); if (ra.IsFaulted) { return(new Result <TryOptionAsync <B> >(TryOptionAsync <B>(ra.Exception))); } if (ra.IsNone) { return(new Result <TryOptionAsync <B> >(TryOptionAsync <B>(None))); } var rb = await ra.Value.Value.Try().ConfigureAwait(false); if (rb.IsFaulted) { return(new Result <TryOptionAsync <B> >(rb.Exception)); } return(new Result <TryOptionAsync <B> >(TryOptionAsync <B>(f(rb.Value)))); } }
public TryOptionAsync <B> Action(TryOptionAsync <A> fa, TryOptionAsync <B> fb) => async() => { var a = fa.Try(); var b = fb.Try(); await Task.WhenAll(a, b); var ra = await a; if (ra.IsFaulted) { return(new OptionalResult <B>(ra.Exception)); } if (ra.IsFaultedOrNone) { return(OptionalResult <B> .None); } var rb = await b; if (rb.IsFaulted) { return(new OptionalResult <B>(rb.Exception)); } if (rb.IsFaultedOrNone) { return(OptionalResult <B> .None); } return(new OptionalResult <B>(rb.Value)); };
public static EitherAsync <L, TryOptionAsync <B> > Traverse <L, A, B>(this TryOptionAsync <EitherAsync <L, A> > ma, Func <A, B> f) { return(new EitherAsync <L, TryOptionAsync <B> >(Go(ma, f))); async Task <EitherData <L, TryOptionAsync <B> > > Go(TryOptionAsync <EitherAsync <L, A> > ma, Func <A, B> f) { var result = await ma.Try().ConfigureAwait(false); if (result.IsBottom) { return(EitherData <L, TryOptionAsync <B> > .Bottom); } if (result.IsFaulted) { return(EitherData.Right <L, TryOptionAsync <B> >(TryOptionAsyncFail <B>(result.Exception))); } if (result.IsNone) { return(EitherData.Right <L, TryOptionAsync <B> >(TryOptionAsync <B>(None))); } var db = await result.Value.Value.Data.ConfigureAwait(false); if (db.State == EitherStatus.IsBottom) { return(EitherData <L, TryOptionAsync <B> > .Bottom); } if (db.State == EitherStatus.IsLeft) { return(EitherData.Left <L, TryOptionAsync <B> >(db.Left)); } return(EitherData.Right <L, TryOptionAsync <B> >(TryOptionAsync <B>(f(db.Right)))); } }
public async Task <bool> EqualsAsync(TryOptionAsync <A> x, TryOptionAsync <A> y) { var dx = await x.Try().ConfigureAwait(false); var dy = await y.Try().ConfigureAwait(false); if (dx.IsBottom && dy.IsBottom) { return(true); } if (dx.IsFaulted && dy.IsFaulted) { return(true); } if (dx.IsNone && dy.IsNone) { return(true); } if (dx.IsSome && dy.IsSome) { return(await default(EqA).EqualsAsync(dx.Value.Value, dy.Value.Value).ConfigureAwait(false)); } else { return(false); } }
public async Task <int> CompareAsync(TryOptionAsync <A> x, TryOptionAsync <A> y) { var dx = await x.Try().ConfigureAwait(false); var dy = await y.Try().ConfigureAwait(false); if (dx.IsBottom && dy.IsBottom) { return(0); } if (dx.IsFaulted && dy.IsFaulted) { return(0); } if (dx.IsNone && dy.IsNone) { return(0); } if (dx.IsSome && dy.IsSome) { return(await default(OrdA).CompareAsync(dx.Value.Value, dy.Value.Value).ConfigureAwait(false)); } if (dx.IsBottom && !dy.IsBottom) { return(-1); } if (!dx.IsBottom && dy.IsBottom) { return(1); } if (dx.IsFaulted && !dy.IsFaulted) { return(-1); } if (!dx.IsFaulted && dy.IsFaulted) { return(1); } if (dx.IsNone && !dy.IsNone) { return(-1); } if (!dx.IsNone && dy.IsNone) { return(1); } if (dx.IsSome && !dy.IsSome) { return(-1); } if (!dx.IsSome && dy.IsSome) { return(1); } return(0); }
public MB BindAsync <MONADB, MB, B>(TryOptionAsync <A> ma, Func <A, Task <MB> > f) where MONADB : struct, MonadAsync <Unit, Unit, MB, B> => default(MONADB).RunAsync(async _ => { try { var ra = await ma.Try(); if (ra.IsBottom) { return(default(MONADB).Fail(new TaskCanceledException())); } if (ra.IsFaulted) { return(default(MONADB).Fail(ra.Exception)); } if (ra.IsFaultedOrNone) { return(default(MONADB).Zero()); } return(await f(ra.Value.Value)); } catch (Exception e) { return(default(MONADB).Fail(e)); } });
public TryOptionAsync <B> Apply(Func <A, A, B> fab, TryOptionAsync <A> fa, TryOptionAsync <A> fb) => async() => { var a = fa.Try(); var b = fb.Try(); await Task.WhenAll(a, b).ConfigureAwait(false); var ra = await a.ConfigureAwait(false); if (ra.IsFaulted) { return(new OptionalResult <B>(ra.Exception)); } if (ra.IsFaultedOrNone) { return(OptionalResult <B> .None); } var rb = await b.ConfigureAwait(false); if (rb.IsFaulted) { return(new OptionalResult <B>(rb.Exception)); } if (rb.IsFaultedOrNone) { return(OptionalResult <B> .None); } return(new OptionalResult <B>(fab(ra.Value.Value, rb.Value.Value))); };
public TryOptionAsync <A> Plus(TryOptionAsync <A> ma, TryOptionAsync <A> mb) => async() => { // Run in parallel var resA = ma.Try(); var resB = mb.Try(); var tasks = Set <OrdTask <OptionalResult <A> >, Task <OptionalResult <A> > >(resA, resB); while (tasks.Count > 0) { // Return first one that completes var completed = await Task.WhenAny(tasks); if (!completed.IsFaulted && !completed.Result.IsFaulted) { return(completed.Result); } tasks = tasks.Remove(completed); } if (!resA.IsFaulted) { return(resA.Result); } if (!resB.IsFaulted) { return(resB.Result); } return(OptionalResult <A> .None); };
public async Task <int> GetHashCodeAsync(TryOptionAsync <A> x) { var dx = await x.Try(); return(dx.IsSome ? await default(HashA).GetHashCodeAsync(dx.Value.Value) : 0); }
/// <summary> /// Performs the given action if the operation results in a failed state /// </summary> /// <param name="t">Current operation</param> /// <param name="ifFail">Action to execute with the exception that caused the failure</param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static TryOptionAsync <T> DoIfFail <T>(this TryOptionAsync <T> t, Action <Exception> ifFail) => async() => { var optionResult = await t.Try(); if (optionResult.IsFaulted) { optionResult.IfFail(ifFail); } return(optionResult); };
public TryOptionAsync <A> Apply(Func <A, A, A> f, TryOptionAsync <A> fa, TryOptionAsync <A> fb) => async() => { // Run in parallel var resA = fa.Try(); var resB = fb.Try(); var completed = await Task.WhenAll(resA, resB); return(!completed[0].IsFaulted && !completed[1].IsFaulted && completed[0].Value.IsSome && completed[1].Value.IsSome ? Option <A> .Some(f(completed[0].Value.Value, completed[1].Value.Value)) : Option <A> .None); // TODO: Propagate exceptions };
public TryOptionAsync <A> Plus(TryOptionAsync <A> ma, TryOptionAsync <A> mb) => async() => { var a = await ma.Try().ConfigureAwait(false); if (!a.IsFaultedOrNone) { return(a); } var b = await mb.Try().ConfigureAwait(false); return(b.IsFaulted && a.IsFaulted ? new OptionalResult <A>(new AggregateException(a.Exception, b.Exception)) : b); };
public TryOptionAsync <B> Apply(Func <A, B> fab, TryOptionAsync <A> fa) => async() => { var a = fa.Try(); var ra = await a; if (ra.IsFaulted) { return(new OptionalResult <B>(ra.Exception)); } if (ra.IsFaultedOrNone) { return(OptionalResult <B> .None); } return(new OptionalResult <B>(fab(ra.Value.Value))); };
public static async Task <TryOptionAsync <B> > Traverse <A, B>(this TryOptionAsync <Task <A> > ma, Func <A, B> f) { var da = await ma.Try().ConfigureAwait(false); if (da.IsBottom) { throw new BottomException(); } if (da.IsNone) { return(TryOptionalAsync <B>(None)); } if (da.IsFaulted) { return(TryOptionAsyncFail <B>(da.Exception)); } #nullable disable
public TryOptionAsync <B> Apply(TryOptionAsync <Func <A, B> > fab, TryOptionAsync <A> fa) => async() => { var f = fab.Try(); var a = fa.Try(); await Task.WhenAll(f, a); if (f.IsFaulted || f.Result.IsFaultedOrNone) { return(new OptionalResult <B>(f.Exception)); } if (a.IsFaulted || a.Result.IsFaultedOrNone) { return(new OptionalResult <B>(a.Exception)); } return(new OptionalResult <B>(f.Result.Value.Value(a.Result.Value.Value))); };
public TryOptionAsync <B> Action(TryOptionAsync <A> fa, TryOptionAsync <B> fb) => async() => { var a = fa.Try(); var b = fb.Try(); await Task.WhenAll(a, b); if (a.IsFaulted || a.Result.IsFaultedOrNone) { return(new OptionalResult <B>(a.Exception)); } if (b.IsFaulted || b.Result.IsFaultedOrNone) { return(new OptionalResult <B>(b.Exception)); } return(new OptionalResult <B>(b.Result.Value)); };
public B Match <B>(TryOptionAsync <A> opt, Func <A, B> Some, Func <B> None) { try { var res = opt.Try().Result; // TODO: No asynchrony if (res.IsFaultedOrNone) { return(None()); } else { return(Some(res.Value.Value)); } } catch { return(None()); } }
public static async ValueTask <TryOptionAsync <B> > Traverse <A, B>(this TryOptionAsync <ValueTask <A> > ma, Func <A, B> f) { var da = await ma.Try().ConfigureAwait(false); if (da.IsBottom) { throw new BottomException(); } if (da.IsNone) { return(TryOptionalAsync <B>(None)); } if (da.IsFaulted) { return(TryOptionAsyncFail <B>(da.Exception)); } var a = await da.Value.Value.ConfigureAwait(false); return(TryOptionAsyncSucc(f(a))); }
public MB Bind <MONADB, MB, B>(TryOptionAsync <A> ma, Func <A, MB> f) where MONADB : struct, Monad <Unit, Unit, MB, B> => default(MONADB).IdAsync(_ => ma.Try().ContinueWith(task => { try { return(task.IsFaulted ? default(MONADB).Fail(task.Exception) : task.IsCanceled ? default(MONADB).Fail(new TaskCanceledException()) : task.Result.IsFaulted ? default(MONADB).Fail(task.Result.Exception) : task.Result.Value.IsNone || task.Result.IsBottom ? default(MONADB).Fail(new TaskCanceledException()) : f(task.Result.Value.Value)); } catch (Exception e) { return(default(MONADB).Fail(e)); } }));
public TryOptionAsync <B> ApplyOption(Func <Option <A>, Option <A>, B> fab, TryOptionAsync <A> fa, TryOptionAsync <A> fb) => async() => { var a = fa.Try(); var b = fb.Try(); await Task.WhenAll(a, b); var ra = await a; if (ra.IsFaulted) { return(new OptionalResult <B>(ra.Exception)); } var rb = await b; if (rb.IsFaulted) { return(new OptionalResult <B>(rb.Exception)); } return(new OptionalResult <B>(fab(ra.Value, rb.Value))); };
public static async Task <TryOptionAsync <B> > Traverse <A, B>(this TryOptionAsync <Task <A> > ma, Func <A, B> f) { var da = await ma.Try(); if (da.IsBottom) { throw new BottomException(); } if (da.IsNone) { return(TryOptionalAsync <B>(None)); } if (da.IsFaulted) { return(TryOptionAsyncFail <B>(da.Exception)); } var a = await da.Value.Value; if (da.Value.Value.IsFaulted) { ExceptionDispatchInfo.Capture(da.Value.Value.Exception.InnerException).Throw(); } return(TryOptionAsyncSucc(f(a))); }
/// <summary> /// Turns the computation into an observable stream /// </summary> /// <typeparam name="A">Bound type</typeparam> /// <typeparam name="B">Returned observable bound type</typeparam> /// <param name="ma">This</param> /// <param name="Some">Function to call when the operation succeeds</param> /// <param name="None">Function to call when the operation succeeds but returns no value</param> /// <param name="Fail">Function to call when the operation fails</param> /// <returns>An observable that represents the result of Succ or Fail</returns> public static IObservable <B> MatchObservable <A, B>(this TryOptionAsync <A> ma, Func <A, IObservable <B> > Some, Func <IObservable <B> > None, Func <Exception, B> Fail) => from ra in ma.Try().ToObservable() from rb in ra.Match(Some, None, e => Observable.Return(Fail(e))) select rb;
public static TryOptionAsync <bool> isFail <T>(TryOptionAsync <T> self) => async() => (await self.Try().ConfigureAwait(false)).IsFaultedOrNone;
public static IObservable <A> ToObservable <A>(this TryOptionAsync <A> ma) => from ra in ma.Try().ToObservable() where ra.IsSome select ra.IfFailOrNone(default(A));
/// <summary> /// Turns the computation into an observable stream /// </summary> /// <typeparam name="A">Bound type</typeparam> /// <typeparam name="R">Returned observable bound type</typeparam> /// <param name="ma">This</param> /// <param name="Some">Function to call when the operation succeeds</param> /// <param name="None">Function to call when the operation succeeds but returns no value</param> /// <param name="Fail">Function to call when the operation fails</param> /// <returns>An observable that represents the result of Succ or Fail</returns> public static IObservable <R> MatchObservable <A, R>(this TryOptionAsync <A> ma, Func <A, R> Some, Func <IObservable <R> > None, Func <Exception, IObservable <R> > Fail) => from ra in ma.Try().ToObservable() from rb in ra.Match(x => Observable.Return(Some(x)), None, Fail) select rb;
public static TryOptionAsync <bool> isFail <T>(TryOptionAsync <T> self) => async() => (await self.Try()).IsFaultedOrNone;