示例#1
0
        public TryAsync <A> Plus(TryAsync <A> ma, TryAsync <A> mb) => async() =>
        {
            // Run in parallel
            var resA = ma.Try();
            var resB = mb.Try();

            var tasks = Set <OrdTask <Result <A> >, Task <Result <A> > >(resA, resB);

            while (tasks.Count > 0)
            {
                // Return first one that completes
                var completed = await Task.WhenAny(tasks).ConfigureAwait(false);

                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(new Result <A>(new AggregateException(resA.Exception, resB.Exception)));
        };
示例#2
0
        public TryAsync <B> Action(TryAsync <A> fa, TryAsync <B> fb) =>
        async() =>
        {
            var a = fa.Try();
            var b = fb.Try();

            await Task.WhenAll(a, b);

            if (a.IsFaulted)
            {
                return(new Result <B>(a.Exception));
            }
            if (b.IsFaulted)
            {
                return(new Result <B>(b.Exception));
            }

            var ra = await a;
            if (ra.IsFaulted)
            {
                return(new Result <B>(ra.Exception));
            }

            var rb = await b;
            if (rb.IsFaulted)
            {
                return(new Result <B>(rb.Exception));
            }

            return(new Result <B>(rb.Value));
        };
示例#3
0
        public static TryOptionAsync <TryAsync <B> > Traverse <A, B>(this TryAsync <TryOptionAsync <A> > ma, Func <A, B> f)
        {
            return(ToTry(() => Go(ma, f)));

            async Task <OptionalResult <TryAsync <B> > > Go(TryAsync <TryOptionAsync <A> > ma, Func <A, B> f)
            {
                var ra = await ma.Try().ConfigureAwait(false);

                if (ra.IsFaulted)
                {
                    return(new OptionalResult <TryAsync <B> >(TryAsync <B>(ra.Exception)));
                }
                var rb = await ra.Value.Try().ConfigureAwait(false);

                if (rb.IsFaulted)
                {
                    return(new OptionalResult <TryAsync <B> >(rb.Exception));
                }
                if (rb.IsNone)
                {
                    return(OptionalResult <TryAsync <B> > .None);
                }
                return(new OptionalResult <TryAsync <B> >(TryAsync <B>(f(rb.Value.Value))));
            }
        }
示例#4
0
        public TryAsync <A> Plus(TryAsync <A> ma, TryAsync <A> mb) => async() =>
        {
            // Run in parallel
            var resA = ma.Try();
            var resB = mb.Try();

            var tasks = Set <OrdTask <Result <A> >, Task <Result <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);
            }
            throw new BottomException();
        };
示例#5
0
    /// <summary>
    /// Invoke a delegate if the Try returns a value successfully
    /// </summary>
    /// <param name="Succ">Delegate to invoke if successful</param>
    public static async Task <Unit> IfSucc <A>(this TryAsync <A> self, Action <A> Succ)
    {
        if (isnull(self))
        {
            throw new ArgumentNullException(nameof(self));
        }
        if (isnull(Succ))
        {
            throw new ArgumentNullException(nameof(Succ));
        }

        try
        {
            var res = await self.Try();

            if (!res.IsFaulted)
            {
                Succ(res.Value);
            }
            return(unit);
        }
        catch (Exception e)
        {
            TryConfig.ErrorLogger(e);
            return(unit);
        }
    }
示例#6
0
    public static async Task <A> IfFail <A>(this TryAsync <A> self, Func <Exception, A> Fail)
    {
        if (isnull(self))
        {
            throw new ArgumentNullException(nameof(self));
        }
        if (isnull(Fail))
        {
            throw new ArgumentNullException(nameof(Fail));
        }

        try
        {
            var res = await self.Try();

            if (res.IsFaulted)
            {
                return(Fail(res.Exception));
            }
            else
            {
                return(res.Value);
            }
        }
        catch (Exception e)
        {
            TryConfig.ErrorLogger(e);
            return(Fail(e));
        }
    }
示例#7
0
 public static TryAsync <R> BiBind <A, R>(this TryAsync <A> self, Func <A, TryAsync <R> > Succ, Func <Exception, TryAsync <R> > Fail) => Memo <R>(async() =>
 {
     var res = await self.Try();
     return(res.IsFaulted
         ? await Fail(res.Exception).Try()
         : await Succ(res.Value).Try());
 });
示例#8
0
 public static TryAsync <B> BiMap <A, B>(this TryAsync <A> self, Func <A, Task <B> > Succ, Func <Exception, Task <B> > Fail) => Memo <B>(async() =>
 {
     var res = await self.Try();
     return(res.IsFaulted
         ? await Fail(res.Exception)
         : await Succ(res.Value));
 });
示例#9
0
        public static EitherAsync <L, TryAsync <B> > Traverse <L, A, B>(this TryAsync <EitherAsync <L, A> > ma, Func <A, B> f)
        {
            return(new EitherAsync <L, TryAsync <B> >(Go(ma, f)));

            async Task <EitherData <L, TryAsync <B> > > Go(TryAsync <EitherAsync <L, A> > ma, Func <A, B> f)
            {
                var result = await ma.Try().ConfigureAwait(false);

                if (result.IsBottom)
                {
                    return(EitherData <L, TryAsync <B> > .Bottom);
                }
                if (result.IsFaulted)
                {
                    return(EitherData.Right <L, TryAsync <B> >(TryAsyncFail <B>(result.Exception)));
                }
                var db = await result.Value.Data.ConfigureAwait(false);

                if (db.State == EitherStatus.IsBottom)
                {
                    return(EitherData <L, TryAsync <B> > .Bottom);
                }
                if (db.State == EitherStatus.IsLeft)
                {
                    return(EitherData.Left <L, TryAsync <B> >(db.Left));
                }
                return(EitherData.Right <L, TryAsync <B> >(TryAsync <B>(f(db.Right))));
            }
        }
示例#10
0
        public TryAsync <B> Apply(TryAsync <Func <A, B> > fab, TryAsync <A> fa) =>
        async() =>
        {
            var f = fab.Try();
            var a = fa.Try();

            await Task.WhenAll(f, a);

            if (f.IsFaulted)
            {
                return(new Result <B>(f.Exception));
            }
            if (a.IsFaulted)
            {
                return(new Result <B>(a.Exception));
            }

            var rf = await f;
            if (rf.IsFaulted)
            {
                return(new Result <B>(rf.Exception));
            }

            var ra = await a;
            if (ra.IsFaulted)
            {
                return(new Result <B>(ra.Exception));
            }

            return(new Result <B>(rf.Value(ra.Value)));
        };
示例#11
0
        public async Task <int> GetHashCodeAsync(TryAsync <A> x)
        {
            var dx = await x.Try().ConfigureAwait(false);

            return(dx.IsSuccess
                ? await default(HashA).GetHashCodeAsync(dx.Value).ConfigureAwait(false)
                : 0);
        }
示例#12
0
 /// <summary>
 /// Impure iteration of the bound value in the structure
 /// </summary>
 /// <returns>
 /// Returns the original unmodified structure
 /// </returns>
 public static TryAsync <A> Do <A>(this TryAsync <A> ma, Action <A> f) => new TryAsync <A>(async() =>
 {
     var r = await ma.Try();
     if (!r.IsFaulted)
     {
         f(r.Value);
     }
     return(r);
 });
示例#13
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 TryAsync <T> DoIfFail <T>(this TryAsync <T> t, Action <Exception> ifFail) => async() =>
        {
            var optionResult = await t.Try();

            if (optionResult.IsFaulted)
            {
                optionResult.IfFail(ifFail);
            }

            return(optionResult);
        };
示例#14
0
 public static TryAsync <A> Filter <A>(this TryAsync <A> self, Func <A, Task <bool> > pred) => Memo(async() =>
 {
     var res = await self.Try();
     if (res.IsFaulted)
     {
         return(res);
     }
     return(await pred(res.Value)
         ? res
         : raise <A>(new BottomException()));
 });
示例#15
0
 public static TryAsync <A> BiFilter <A>(this TryAsync <A> self, Func <A, Task <bool> > Succ, Func <Exception, Task <bool> > Fail) => Memo <A>(async() =>
 {
     var res = await self.Try();
     return(res.IsFaulted
         ? await Fail(res.Exception)
             ? res.Value
             : raise <A>(new BottomException())
         : await Succ(res.Value)
             ? res.Value
             : raise <A>(new BottomException()));
 });
示例#16
0
        public TryAsync <A> Plus(TryAsync <A> ma, TryAsync <A> mb) => async() =>
        {
            var a = await ma.Try();

            if (a.IsSuccess)
            {
                return(a);
            }
            var b = await mb.Try();

            return(b.IsSuccess
                ? b
                : new Result <A>(new AggregateException(a.Exception, b.Exception)));
        };
示例#17
0
        public static async ValueTask <TryAsync <B> > Traverse <A, B>(this TryAsync <ValueTask <A> > ma, Func <A, B> f)
        {
            var da = await ma.Try().ConfigureAwait(false);

            if (da.IsBottom)
            {
                throw new BottomException();
            }
            if (da.IsFaulted)
            {
                return(TryAsyncFail <B>(da.Exception));
            }
            var a = await da.Value.ConfigureAwait(false);

            return(TryAsyncSucc(f(a)));
        }
示例#18
0
    /// <summary>
    /// Memoize the computation so that it's only run once
    /// </summary>
    public static TryAsync <A> Memo <A>(this TryAsync <A> ma)
    {
        bool       run    = false;
        Result <A> result = new Result <A>();

        return(new TryAsync <A>(async() =>
        {
            if (run)
            {
                return result;
            }
            result = await ma.Try();
            run = true;
            return result;
        }));
    }
示例#19
0
    /// <summary>
    /// Memoize the computation so that it's only run once
    /// </summary>
    public static TryAsync <A> Memo <A>(this TryAsync <A> ma)
    {
        bool run    = false;
        var  result = Result <A> .Bottom.AsTask();

        return(new TryAsync <A>(() =>
        {
            if (run)
            {
                return result;
            }
            result = ma.Try();
            run = true;
            return result;
        }));
    }
示例#20
0
        public async Task <int> CompareAsync(TryAsync <A> x, TryAsync <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.IsSuccess && dy.IsSuccess)
            {
                return(await default(OrdA).CompareAsync(dx.Value, dy.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.IsSuccess && !dy.IsSuccess)
            {
                return(-1);
            }
            if (!dx.IsSuccess && dy.IsSuccess)
            {
                return(1);
            }
            return(0);
        }
示例#21
0
    public static async Task <R> Match <A, R>(this TryAsync <A> self, Func <A, Task <R> > Succ, R Fail)
    {
        if (isnull(Succ))
        {
            throw new ArgumentNullException(nameof(Succ));
        }
        if (isnull(Fail))
        {
            throw new ArgumentNullException(nameof(Fail));
        }

        var res = await self.Try();

        return(res.IsFaulted
            ? Fail
            : await Succ(res.Value));
    }
示例#22
0
    public static async Task <A> IfFailThrow <A>(this TryAsync <A> self)
    {
        try
        {
            var res = await self.Try();

            if (res.IsFaulted)
            {
                throw new InnerException(res.Exception);
            }
            return(res.Value);
        }
        catch (Exception e)
        {
            TryConfig.ErrorLogger(e);
            throw;
        }
    }
示例#23
0
        public static async Task <TryAsync <B> > Traverse <A, B>(this TryAsync <Task <A> > ma, Func <A, B> f)
        {
            var da = await ma.Try();

            if (da.IsBottom)
            {
                throw new BottomException();
            }
            if (da.IsFaulted)
            {
                return(TryAsyncFail <B>(da.Exception));
            }
            var a = await da.Value;

            if (da.Value.IsFaulted)
            {
                ExceptionDispatchInfo.Capture(da.Value.Exception.InnerException).Throw();
            }
            return(TryAsyncSucc(f(a)));
        }
示例#24
0
        public async Task <B> MatchAsync <B>(TryAsync <A> opt, Func <A, B> Some, Func <Task <B> > NoneAsync)
        {
            try
            {
                var res = await opt.Try().ConfigureAwait(false);

                if (res.IsFaulted)
                {
                    return(Check.NullReturn(await NoneAsync().ConfigureAwait(false)));
                }
                else
                {
                    return(Check.NullReturn(Some(res.Value)));
                }
            }
            catch
            {
                return(Check.NullReturn(await NoneAsync().ConfigureAwait(false)));
            }
        }
示例#25
0
        public async Task <B> MatchUnsafe <B>(TryAsync <A> opt, Func <A, B> Some, Func <B> None)
        {
            try
            {
                var res = await opt.Try().ConfigureAwait(false);

                if (res.IsFaulted)
                {
                    return(None());
                }
                else
                {
                    return(Some(res.Value));
                }
            }
            catch
            {
                return(None());
            }
        }
示例#26
0
        public async Task <B> MatchUnsafeAsync <B>(TryAsync <A> opt, Func <A, Task <B> > SomeAsync, Func <Task <B> > NoneAsync)
        {
            try
            {
                var res = await opt.Try().ConfigureAwait(false);

                if (res.IsFaulted)
                {
                    return(await NoneAsync().ConfigureAwait(false));
                }
                else
                {
                    return(await SomeAsync(res.Value).ConfigureAwait(false));
                }
            }
            catch
            {
                return(await NoneAsync().ConfigureAwait(false));
            }
        }
示例#27
0
        public async Task <B> Match <B>(TryAsync <A> opt, Func <A, B> Some, Func <B> None)
        {
            try
            {
                var res = await opt.Try();

                if (res.IsFaulted)
                {
                    return(Check.NullReturn(None()));
                }
                else
                {
                    return(Check.NullReturn(Some(res.Value)));
                }
            }
            catch
            {
                return(Check.NullReturn(None()));
            }
        }
示例#28
0
        public async Task <B> MatchAsync <B>(TryAsync <A> opt, Func <A, Task <B> > SomeAsync, Func <Task <B> > NoneAsync)
        {
            try
            {
                var res = await opt.Try();

                if (res.IsFaulted)
                {
                    return(Check.NullReturn(await NoneAsync()));
                }
                else
                {
                    return(Check.NullReturn(await SomeAsync(res.Value)));
                }
            }
            catch
            {
                return(Check.NullReturn(await NoneAsync()));
            }
        }
示例#29
0
 public MB Bind <MONADB, MB, B>(TryAsync <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.IsBottom
                             ? default(MONADB).Fail(new TaskCanceledException())
                             : f(task.Result.Value));
     }
     catch (Exception e)
     {
         return(default(MONADB).Fail(e));
     }
 }));
示例#30
0
        public async Task <B> MatchUnsafeAsync <B>(TryAsync <A> opt, Func <A, Task <B> > Some, Func <Task <B> > None)
        {
            try
            {
                var res = await opt.Try();

                if (res.IsFaulted)
                {
                    return(await None());
                }
                else
                {
                    return(await Some(res.Value));
                }
            }
            catch
            {
                return(await None());
            }
        }