コード例 #1
0
        static void Main(string[] args)
        {
            string word = "five";

            // Note: We're creating an either with the left type as int and the right type as string.
            // You can assign either type to an either
            Either <int, string> amount = 5;

            amount = word;
            var emptyEither = new Either <int, string>();

            // Note you can do the same transformations you did on a Box<T> on an Either because it too is a Monad and it too has a Bind(), Map(), Select() and SelectMany() extension method.
            // This transformation occurs on the right hand value, provided that the either contains the right hand value and not the left (this is the inbuilt validation or short-circuiting Monad idea in action)

            var resultA = amount.Bind(str => TransformRight(str)); // Extract EitherData from either once validated ie that its not a right value, run transform function.

            amount = 25;

            // notice that it's biased to its right value and only cares about running a transform on a right type.
            // The validation within Either's Bind() will check for a Right Type and then run the provided transform, if its left it will return what it has (25) but no transform will occur
            var resultB = amount.Bind(integer => TransformRight(integer)); // Wont run transformation because the validation will fail because its a left type.

            Console.WriteLine($"The value of resulta is '{resultA}' and the result of result b is '{resultB}' and an empty either looks like this '{emptyEither}' ");

            // notice how Either's bind function will extract the right part, if validation succeeds and runs the transformation as expected.
            Either <int, string> TransformRight(string extractedRight)
            {
                Either <int, string> result = extractedRight.ToUpper(); // Like all Bind functions we need to lift the result into the monad ie Either type

                return(result);
            }
        }
コード例 #2
0
        Either <AccountError, decimal> AccountBalanceById(uint accountId)
        {
            Either <AccountError, uint>    existingAccountId = ExistingAccountId(accountId);
            Either <AccountError, decimal> accountBalance    = existingAccountId.Bind(AccountBalance);

            return(accountBalance);
        }
コード例 #3
0
        internal static Either <TAccumulate, TRight> FoldImpl <TSource, TAccumulate, TRight>(
            this IEnumerable <TSource> source,
            TAccumulate seed,
            Func <TAccumulate, TSource, Either <TAccumulate, TRight> > accumulator,
            Func <Either <TAccumulate, TRight>, bool> predicate)
        {
            Debug.Assert(source != null);
            Debug.Assert(accumulator != null);
            Debug.Assert(predicate != null);

            Either <TAccumulate, TRight> retval = Either <TAccumulate, TRight> .OfLeft(seed);

            using (var iter = source.GetEnumerator())
            {
                while (predicate(retval) && iter.MoveNext())
                {
                    if (retval == null)
                    {
                        continue;
                    }

                    retval = retval.Bind(val => accumulator(val, iter.Current));
                }
            }

            return(retval);
        }
コード例 #4
0
ファイル: EitherExtTests.cs プロジェクト: fambda/fambda
        public void BindShouldSucceedWhenLeft()
        {
            // Arrange
            var value = "value";
            var left  = Left(value);
            Either <string, int> either = left;

            Func <int, Either <string, bool> > toTrueBoolWhenEitherRightAndIntOne = (i) =>
            {
                if (i.Equals(1))
                {
                    return(Right(true));
                }
                else
                {
                    return(Left("false"));
                };
            };

            // Act
            var result = either.Bind(toTrueBoolWhenEitherRightAndIntOne);


            // Assert
            result.Left.Should().Be("value");
        }
コード例 #5
0
        internal static Either <TSource, TRight> ReduceImpl <TSource, TRight>(
            this IEnumerable <TSource> source,
            Func <TSource, TSource, Either <TSource, TRight> > accumulator,
            Func <Either <TSource, TRight>, bool> predicate)
        {
            Debug.Assert(source != null);
            Debug.Assert(accumulator != null);
            Debug.Assert(predicate != null);

            using (var iter = source.GetEnumerator())
            {
                if (!iter.MoveNext())
                {
                    throw new InvalidOperationException("Source sequence was empty.");
                }

                Either <TSource, TRight> retval = Either <TSource, TRight> .OfLeft(iter.Current);

                while (predicate(retval) && iter.MoveNext())
                {
                    if (retval == null)
                    {
                        continue;
                    }

                    retval = retval.Bind(val => accumulator(val, iter.Current));
                }

                return(retval);
            }
        }
コード例 #6
0
 public static Either <TLeft, TRightOutput> SelectSafe <TLeft, TRightInput, TRightMedium, TRightOutput>(
     this Either <TLeft, TRightInput> source,
     Func <TRightInput, Either <TLeft, TRightMedium> > mediumSelector,
     Func <TRightInput, TRightMedium, TRightOutput> resultSelector)
 {
     return(source.Bind(rightInput =>
                        mediumSelector(rightInput)
                        .Map(rightMedium => resultSelector(rightInput, rightMedium))));
 }
コード例 #7
0
        public void should_bind_on_right_values()
        {
            Either <string, int> sut = Functional.Right(10);

            Either <string, int> Double(int i)
            {
                return(Functional.Right(i * 2));
            }

            var result = sut.Bind(Double);

            var match = result.Match(l => - 1, r => r);

            match.Should().Be(20);
        }
コード例 #8
0
        public void should_bind_on_right_values_on_failing_functions()
        {
            Either <string, int> sut = Right(10);

            Either <string, int> Double(int i)
            {
                return(Left("some error"));
            }

            var result = sut.Bind(Double);

            var match = result.Match(l => l, r => "should not happen");

            match.Should().Be("some error");
        }
コード例 #9
0
        public void should_bind_on_left_values()
        {
            Either <string, int> sut = Functional.Left("some error");

            Either <string, int> Double(int i)
            {
                return(Functional.Right(i * 2));
            }

            var result = sut.Bind(Double);

            var match = result.Match(l => l, r => "should not happen");

            match.Should().Be("some error");
        }
コード例 #10
0
        /// <summary>
        /// This methods extracts the value of a RETURN structure (BAPIRET or BAPIRET2) and processes it's value as
        /// left value if return contains a non-successful result (abort or error).
        /// This method accepts a EitherAsync with any right value.
        /// </summary>
        /// <param name="self"></param>
        /// <returns>A <see cref="EitherAsync{RfcErrorInfo,IFunction}"/> with the function as right value or the left value.</returns>
        public static Either <RfcErrorInfo, IFunction> HandleReturn(this Either <RfcErrorInfo, IFunction> self)
        {
            return(self.Bind(f => (
                                 from ret in f.GetStructure("RETURN")
                                 from type in ret.GetField <string>("TYPE")
                                 from id in ret.GetField <string>("ID")
                                 from number in ret.GetField <string>("NUMBER")
                                 from message in ret.GetField <string>("MESSAGE")
                                 from v1 in ret.GetField <string>("MESSAGE_V1")
                                 from v2 in ret.GetField <string>("MESSAGE_V2")
                                 from v3 in ret.GetField <string>("MESSAGE_V3")
                                 from v4 in ret.GetField <string>("MESSAGE_V4")

                                 from _ in ErrorOrResult(f, type, id, number, message, v1, v2, v3, v4)
                                 select f)));
        }
コード例 #11
0
        // Either - Exception handling
        static void Eleven()
        {
            Option <string> result = GetHtml("invalidurl");              // None. ie it will swallow the exception

            Either <Exception, string> resultb = GetHtmlE("invalidurl"); // Left(System.InvalidOperationException)

            // Did the request throw an exception or return html?
            resultb.Match(
                Left: ex => HandleException(ex),
                Right: ProcessPipeline
                );

            // Keep in the elevated context
            var resultc = resultb.Map(x => x.Substring(0, 1)); // if not an Exception ie Right, then apply a lambda expression

            // Bind an Either<Exception, string> with an Either<Exception, string>
            var resultd = resultb.Bind(DoSomething);
        }
コード例 #12
0
        public void Bind_Error_ShouldInvokeFunc()
        {
            var result = value.Bind(IsPositive);

            Assert.AreEqual(new Either <Exception, bool>(true), result);
        }
コード例 #13
0
 public static Either <RfcErrorInfo, TDataContainer> SetField <TDataContainer, T>(this Either <RfcErrorInfo, TDataContainer> self, string name, T value)
     where TDataContainer : IDataContainer
 {
     return(self.Bind(s => s.SetField(name, value).Map(u => s)));
 }
コード例 #14
0
        public void Bind_Error_ShouldKeepLeft()
        {
            var result = error.Bind(IsPositive);

            Assert.AreEqual(new Either <Exception, bool>(exception), result);
        }
コード例 #15
0
 static public Either <RfcErrorInfo, IEnumerable <TResult> > MapStructure <TResult>(this Either <RfcErrorInfo, ITable> eitherTable, Func <IStructure, Either <RfcErrorInfo, TResult> > mapperFunc)
 {
     return(eitherTable.Bind(table => table.Rows.Map(mapperFunc).Traverse(l => l)));
 }
コード例 #16
0
 static public Either <RfcErrorInfo, TResult> MapStructure <TCont, TResult>(this Either <RfcErrorInfo, TCont> self, string structureName, Func <IStructure, Either <RfcErrorInfo, TResult> > mapperFunc)
     where TCont : IDataContainer
 {
     return(self.Bind(s => s.GetStructure(structureName).Bind(mapperFunc)));
 }
コード例 #17
0
 public static Either <RfcErrorInfo, T> GetField <T>(this Either <RfcErrorInfo, IFunction> self, string name)
 {
     return(self.Bind(s => s.GetField <T>(name)));
 }
コード例 #18
0
 public static Either <RfcErrorInfo, TDataContainer> SetStructure <TDataContainer, TResult>(this Either <RfcErrorInfo, TDataContainer> self, string structureName, Func <Either <RfcErrorInfo, IStructure>, TResult> map)
     where TDataContainer : IDataContainer
 {
     return(self.Bind(dc =>
                      dc.GetStructure(structureName).Use(used => used.Apply(map).Apply(_ => used)).Map(_ => dc)));
 }
コード例 #19
0
 public static Either <X, B> SelectMany <X, A, B>(this Either <X, A> either, Func <A, Either <X, B> > selectManyFunc)
 {
     return(either.Bind(selectManyFunc));
 }
コード例 #20
0
 public static Either <L, R> Flatten <L, R>(this Either <L, Either <L, R> > ma) =>
 ma.Bind(identity);
コード例 #21
0
 public static Either <X, C> SelectMany <X, A, B, C>(this Either <X, A> either, Func <A, Either <X, B> > selectManyFunc, Func <A, B, C> combineFunc)
 {
     return(either.Bind(a => selectManyFunc(a).Bind(b => Either.Right <X, C>(combineFunc(a, b)))));
 }
コード例 #22
0
 // 1. Implement Apply for Either and Exceptional
 static Either <L, R> Apply <L, T, R>(this Either <L, Func <T, R> > eitherF, Either <L, T> eitherT)
 => eitherT.Bind(t => eitherF.Bind <L, Func <T, R>, R>(f => f(t)));
コード例 #23
0
 public static Either <TFailure, Option <TResult> > MapO <TFailure, TSource, TResult>(
     this Either <TFailure, Option <TSource> > @this,
     Func <TSource, Either <TFailure, TResult> > f)
 => @this.Bind(opt => opt.Match(t => f(t).Map(Optional), () => Right <TFailure, Option <TResult> >(Option <TResult> .None)));
コード例 #24
0
ファイル: Bind.cs プロジェクト: jedahu/Jib
 public static Either <X, A> Join <X, A>(this Either <X, Either <X, A> > either)
 {
     return(either.Bind(a => a));
 }
コード例 #25
0
 public static Either <L, RR> SelectMany <L, R, RR>(this Either <L, R> either, Func <R, Either <L, RR> > func)
 => either.Bind(func);
コード例 #26
0
 public static Either <X, B> Ap <X, A, B>(this Either <X, Func <A, B> > f, Either <X, A> arg)
 {
     return(f.Bind(f0 => arg.Map(f0)));
 }
コード例 #27
0
 public static Either <TLeft, TRightOutput> SelectSafe <TLeft, TRightInput, TRightOutput>(
     this Either <TLeft, TRightInput> source, Func <TRightInput, Either <TLeft, TRightOutput> > selector)
 {
     return(source.Bind(selector));
 }