public static TryOption <Eff <B> > Traverse <A, B>(this Eff <TryOption <A> > ma, Func <A, B> f) => () => { var mb = ma.Run(); if (mb.IsBottom) { return(OptionalResult <Eff <B> > .None); } if (mb.IsFail) { return(new OptionalResult <Eff <B> >(FailEff <B>(mb.Error))); } var mr = mb.Value.Try(); if (mr.IsBottom) { return(OptionalResult <Eff <B> > .None); } if (mr.IsFaulted) { return(new OptionalResult <Eff <B> >(mr.Exception)); } if (mr.IsNone) { return(OptionalResult <Eff <B> > .None); } return(new OptionalResult <Eff <B> >(SuccessEff <B>(f(mr.Value.Value)))); };
public static TryOptionAsync <Eff <B> > Traverse <A, B>(this Eff <TryOptionAsync <A> > ma, Func <A, B> f) { return(ToTry(() => Go(ma, f))); async Task <OptionalResult <Eff <B> > > Go(Eff <TryOptionAsync <A> > ma, Func <A, B> f) { var ra = ma.Run(); if (ra.IsFail) { return(new OptionalResult <Eff <B> >(FailEff <B>(ra.Error))); } var rb = await ra.Value.Try().ConfigureAwait(false); if (rb.IsFaulted) { return(new OptionalResult <Eff <B> >(rb.Exception)); } if (rb.IsNone) { return(OptionalResult <Eff <B> > .None); } return(OptionalResult <Eff <B> > .Some(SuccessEff <B>(f(rb.Value.Value)))); } }
/// <summary> /// Create a new cancellation context and run the provided Aff in that context /// </summary> /// <param name="ma">Operation to run in the next context</param> /// <typeparam name="RT">Runtime environment</typeparam> /// <typeparam name="A">Bound value type</typeparam> /// <returns>An asynchronous effect that captures the operation running in context</returns> public static Eff <RT, A> localCancel <RT, A>(Eff <RT, A> ma) where RT : struct, HasCancel <RT> => EffMaybe <RT, A>(rt => { var rt1 = rt.LocalCancel; using (rt1.CancellationTokenSource) { return(ma.ReRun(rt1)); } });
public static async ValueTask <Eff <B> > Traverse <A, B>(this Eff <ValueTask <A> > ma, Func <A, B> f) { var mr = ma.Run(); if (mr.IsBottom) { return(FailEff <B>(BottomException.Default)); } else if (mr.IsFail) { return(FailEff <B>(mr.Error)); } return(SuccessEff <B>(f(await mr.Value.ConfigureAwait(false)))); }
public static Validation <Fail, Eff <B> > Traverse <Fail, A, B>(this Eff <Validation <Fail, A> > ma, Func <A, B> f) { var tres = ma.Run(); if (tres.IsBottom || tres.IsFail) { return(Validation <Fail, Eff <B> > .Success(FailEff <B>(tres.Error))); } else if (tres.Value.IsFail) { return(Validation <Fail, Eff <B> > .Fail((Seq <Fail>) tres.Value)); } else { return(Validation <Fail, Eff <B> > .Success(SuccessEff(f((A)tres.Value)))); } }
/// <summary> /// Safely use a disposable resource /// </summary> /// <param name="Acq">Acquire resource</param> /// <param name="Use">Use resource</param> public static Eff <R> use <H, R>(Eff <H> Acq, Func <H, Eff <R> > Use) where H : IDisposable => EffMaybe(() => { var h = Acq.ReRun(); if (h.IsFail) { return(h.Cast <R>()); } try { return(Use(h.Value).Run()); } finally { h.Value?.Dispose(); } });
/// <summary> /// Safely use a disposable resource /// </summary> /// <param name="Acq">Acquire resource</param> /// <param name="Use">Use resource</param> public static Aff <R> use <H, R>(Eff <H> Acq, Func <H, Aff <R> > Use) where H : IDisposable => AffMaybe(async() => { var h = Acq.ReRun(); if (h.IsFail) { return(h.Cast <R>()); } try { return(await Use(h.Value).Run().ConfigureAwait(false)); } finally { h.Value?.Dispose(); } });
/// <summary> /// Safely use a disposable resource /// </summary> /// <param name="Acq">Acquire resource</param> /// <param name="Use">Use resource</param> public static Aff <RT, R> use <RT, H, R>(Eff <H> Acq, Func <H, Aff <RT, R> > Use) where RT : struct, HasCancel <RT> where H : IDisposable => AffMaybe <RT, R>(async env => { var h = Acq.ReRun(); if (h.IsFail) { return(h.Cast <R>()); } try { return(await Use(h.Value).Run(env).ConfigureAwait(false)); } finally { h.Value?.Dispose(); } });
/// <summary> /// Safely use a disposable resource /// </summary> /// <param name="Acq">Acquire resource</param> /// <param name="Use">Use resource</param> public static Eff <RT, R> use <RT, H, R>(Eff <H> Acq, Func <H, Eff <RT, R> > Use) where RT : struct, HasCancel <RT> where H : IDisposable => EffMaybe <RT, R>(env => { var h = Acq.ReRun(); if (h.IsFail) { return(h.Cast <R>()); } try { return(Use(h.Value).Run(env)); } finally { h.Value?.Dispose(); } });
public static Option <Eff <B> > Traverse <A, B>(this Eff <Option <A> > ma, Func <A, B> f) { var tres = ma.Run(); if (tres.IsBottom) { return(None); } else if (tres.IsFail) { return(Some(FailEff <B>(tres.Error))); } else if (tres.Value.IsNone) { return(None); } else { return(Some(SuccessEff(f(tres.Value.Value)))); } }
public static EitherUnsafe <L, Eff <B> > Traverse <L, A, B>(this Eff <EitherUnsafe <L, A> > ma, Func <A, B> f) { var tres = ma.Run(); if (tres.IsBottom) { return(EitherUnsafe <L, Eff <B> > .Bottom); } else if (tres.IsFail) { return(RightUnsafe(FailEff <B>(tres.Error))); } else if (tres.Value.IsLeft) { return(EitherUnsafe <L, Eff <B> > .Left((L)tres.Value)); } else { return(EitherUnsafe <L, Eff <B> > .Right(SuccessEff(f((A)tres.Value)))); } }
public static EitherAsync <L, Eff <B> > Traverse <L, A, B>(this Eff <EitherAsync <L, A> > ma, Func <A, B> f) { try { return(new EitherAsync <L, Eff <B> >(Go(ma, f))); async Task <EitherData <L, Eff <B> > > Go(Eff <EitherAsync <L, A> > ma, Func <A, B> f) { var ra = ma.Run(); if (ra.IsBottom) { return(EitherData <L, Eff <B> > .Bottom); } if (ra.IsFail) { return(EitherData.Right <L, Eff <B> >(FailEff <B>(ra.Error))); } var da = await ra.Value.Data.ConfigureAwait(false); if (da.State == EitherStatus.IsBottom) { return(EitherData <L, Eff <B> > .Bottom); } if (da.State == EitherStatus.IsLeft) { return(EitherData.Left <L, Eff <B> >(da.Left)); } return(EitherData.Right <L, Eff <B> >(SuccessEff <B>(f(da.Right)))); } } catch (Exception e) { return(FailEff <B>(e)); } }
public static EitherUnsafe <L, Eff <A> > Sequence <L, A>(this Eff <EitherUnsafe <L, A> > ta) => ta.Traverse(identity);
public static Seq <Eff <A> > Sequence <A>(this Eff <Seq <A> > ta) => ta.Traverse(identity);
public static EitherAsync <L, Eff <B> > Sequence <L, A, B>(this Eff <A> ta, Func <A, EitherAsync <L, B> > f) => ta.Map(f).Traverse(Prelude.identity);
public static TryAsync <Eff <A> > Sequence <A>(this Eff <TryAsync <A> > ta) => ta.Traverse(identity);
/// <summary> /// Catch an error if the error matches the argument provided /// </summary> public static Eff <RT, A> Catch <RT, A>(this Eff <RT, A> ma, Error error, Eff <A> Fail) where RT : struct, HasCancel <RT> => ma | matchError(e => e.Is(error), _ => Fail);
/// <summary> /// Catch an error if the error matches the argument provided /// </summary> public static Eff <A> Catch <A>(this Eff <A> ma, Error error, Eff <A> Fail) => ma | matchError(e => e.Is(error), _ => Fail);
/// <summary> /// Catch an error if the error `Code` matches the `errorCode` argument provided /// </summary> public static Eff <RT, A> Catch <RT, A>(this Eff <RT, A> ma, int errorCode, Func <Error, Eff <A> > Fail) where RT : struct, HasCancel <RT> => ma | matchError(e => e.Code == errorCode, Fail);
/// <summary> /// Catch an error if the error `Code` matches the `errorCode` argument provided /// </summary> public static Eff <A> Catch <A>(this Eff <A> ma, int errorCode, Func <Error, Eff <A> > Fail) => ma | matchError(e => e.Code == errorCode, Fail);
public static TryAsync <Eff <B> > Sequence <A, B>(this Eff <A> ta, Func <A, TryAsync <B> > f) => ta.Map(f).Traverse(Prelude.identity);
public static Eff <RT, A> Repeat(Eff <RT, A> ma, Schedule schedule) => schedule.Run(ma, static x => x.IsSucc);
/// <summary> /// Catch all errors /// </summary> public static Eff <RT, A> Catch <RT, A>(this Eff <RT, A> ma, Eff <RT, A> Fail) where RT : struct, HasCancel <RT> => ma | matchError(static _ => true, e => Fail);
public static Eff <RT, Eff <A> > Sequence <RT, A>(this Eff <Eff <RT, A> > mma) where RT : struct => mma.Traverse(identity);
public static Validation <Fail, Eff <B> > Sequence <Fail, A, B>(this Eff <A> ta, Func <A, Validation <Fail, B> > f) => ta.Map(f).Traverse(Prelude.identity);
/// <summary> /// Catch an error if the error message matches the `errorText` argument provided /// </summary> public static Eff <RT, A> Catch <RT, A>(this Eff <RT, A> ma, string errorText, Eff <A> Fail) where RT : struct, HasCancel <RT> => ma | matchError(e => e.Message == errorText, _ => Fail);
public static Lst <Eff <B> > Traverse <A, B>(this Eff <Lst <A> > ma, Func <A, B> f) => ma.Match( Fail: ex => List(FailEff <B>(ex)), Succ: xs => xs.Map(x => SuccessEff <B>(f(x)))).Run().Value;
public static Lst <Eff <A> > Sequence <A>(this Eff <Lst <A> > ta) => ta.Traverse(identity);
public static Eff <RT, Eff <B> > Sequence <RT, A, B>(this Eff <A> ta, Func <A, Eff <RT, B> > f) where RT : struct => ta.Map(f).Sequence();
public static Aff <Eff <B> > Sequence <A, B>(this Eff <A> ta, Func <A, Aff <B> > f) => ta.Map(f).Sequence();