【问题标题】:how to use applicative validation using languageext?如何使用语言文本进行应用验证?
【发布时间】:2020-08-11 10:29:38
【问题描述】:

我正在尝试将使用应用验证的示例与教学库 LaYumba 移植到 LanguageExt

这是 LaYumba 代码(按预期工作):

using System;
using System.Linq;
using FluentAssertions;
using LaYumba.Functional;
using Xunit;
using static LaYumba.Functional.F;

namespace DemoTests._1_LaYumbaDemo
{
    public class Demo
    {
        [Fact]
        public void Sum_validation()
        {
            // Arrange
            Func<int, int, int, int> sum = (a, b, c) => a + b + c;

            Func<int, Validation<int>> onlyPositive = i
                => i > 0
                    ? Valid(i)
                    : Error($"Number {i} is not positive.");

            Validation<int> AddNumbers(int a, int b, int c)
            {
                return Valid(sum) // returns int -> int -> int -> int
                    .Apply(onlyPositive(a)) // returns int -> int -> int
                    .Apply(onlyPositive(b)) // returns int -> int
                    .Apply(onlyPositive(c)); // returns int
            }

            // Act
            var result = AddNumbers(1, 2, 3);

            // Assert
            result.Match(
                _ => true.Should().BeFalse(),
                x => x.Should().Be(6));
        }

        [Fact]
        public void Sum_validation_with_failures()
        {
            // Arrange
            Func<int, int, int, int> sum = (a, b, c) => a + b + c;

            Func<int, Validation<int>> onlyPositive = i
                => i > 0
                    ? Valid(i)
                    : Error($"Number {i} is not positive.");

            Validation<int> AddNumbers(int a, int b, int c)
            {
                return Valid(sum) // returns int -> int -> int -> int
                    .Apply(onlyPositive(a)) // returns int -> int -> int
                    .Apply(onlyPositive(b)) // returns int -> int
                    .Apply(onlyPositive(c)); // returns int
            }

            // Act
            var result = AddNumbers(-1, -2, -3);

            // Assert
            result.Match(
                errors => errors.Select(x => x.Message)
                    .Should()
                    .Contain("Number -1 is not positive.")
                    .And.Contain("Number -2 is not positive.")
                    .And.Contain("Number -3 is not positive."),
                x => true.Should().BeFalse());
        }
    }
}

这里是我需要一些帮助的 LanguageExt 代码:如何将 sum 函数“提升”为某物,以便 Apply 可以像前面的示例一样使用它?

using System;
using FluentAssertions;
using LanguageExt;
using LanguageExt.UnitTesting;
using Xunit;
using static LanguageExt.Prelude;

namespace DemoTests._2_LanguageExtDemo
{
    public class Demo
    {
        [Fact]
        public void Sum_validation()
        {
            // Arrange
            Func<int, int, int, int> sum = (a, b, c) => a + b + c;

            Func<int, Validation<Error, int>> onlyPositive = i
                => i > 0
                    ? Success<Error, int>(i)
                    : Fail<Error, int>(Error.New("ups"));

            Validation<Error, int> AddNumbers(int a, int b, int c)
            {
                // how to lift `sum` into an applicative which other functions
                // can apply to??
                return null;
            }


            // Act
            var result = AddNumbers(1, 2, 3);

            // Assert
            result.ShouldBeSuccess(x => x.Should().Be(6));
        }
    }

    public class Error : NewType<Error, string>
    {
        public Error(string e) : base(e)
        {
        }
    }
}

这是一个示例项目:https://github.com/draptik/csharp-applicative-validation/tree/v1

【问题讨论】:

    标签: c# functional-programming applicative language-ext


    【解决方案1】:

    我查看了验证的语言扩展测试,并在最后一个函数中复制了 it's done there 的方式:

    生成的测试文件是:

    using System;
    using FluentAssertions;
    using LanguageExt;
    using LanguageExt.UnitTesting;
    using Xunit;
    using static LanguageExt.Prelude;
    
    namespace DemoTests._2_LanguageExtDemo
    {
        public class Demo
        {
            [Fact]
            public void Sum_validation()
            {
                // Arrange
                Func<int, int, int, int> sum = (a, b, c) => a + b + c;
    
                Func<int, Validation<Error, int>> onlyPositive = i
                    => i > 0
                        ? Success<Error, int>(i)
                        : Fail<Error, int>(Error.New("ups"));
    
                Validation<Error, int> AddNumbers(int a, int b, int c)
                {
                    return (onlyPositive(a), onlyPositive(b), onlyPositive(c)).Apply(sum);
                }
    
                // Act
                var result = AddNumbers(1, 2, 3);
    
                // Assert
                result.ShouldBeSuccess(x => x.Should().Be(6));
            }
    
            [Fact]
            public void Sum_validation_OneError()
            {
                // Arrange
                Func<int, int, int, int> sum = (a, b, c) => a + b + c;
    
                Func<int, Validation<Error, int>> onlyPositive = i
                    => i > 0
                        ? Success<Error, int>(i)
                        : Fail<Error, int>(Error.New("ups"));
    
                Validation<Error, int> AddNumbers(int a, int b, int c)
                {
                    return (onlyPositive(a), onlyPositive(b), onlyPositive(c)).Apply(sum);
                }
    
                // Act
                var result = AddNumbers(-1, 2, 3);
    
                // Assert
                result.ShouldBeFail(x => x.Should().BeEquivalentTo(Error.New("ups")));
            }
    
            [Fact]
            public void Sum_validation_ThreeErrors()
            {
                var error = Error.New("ups");
    
                // Arrange
                Func<int, int, int, int> sum = (a, b, c) => a + b + c;
    
                Func<int, Validation<Error, int>> onlyPositive = i
                    => i > 0
                        ? Success<Error, int>(i)
                        : Fail<Error, int>(error);
    
                Validation<Error, int> AddNumbers(int a, int b, int c)
                {
                    return (onlyPositive(a), onlyPositive(b), onlyPositive(c)).Apply(sum);
                }
    
    
                // Act
                var result = AddNumbers(-1, -2, -3);
    
                // Assert
                result.ShouldBeFail(x => x.Should().BeEquivalentTo(new System.Collections.Generic.List<Error>{ error, error, error }));
            }
        }
    
        public class Error : NewType<Error, string>
        {
            public Error(string e) : base(e)
            {
            }
        }
    }
    

    【讨论】:

    • 正是我想要的。很棒。
    猜你喜欢
    • 1970-01-01
    • 2015-11-27
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多