如何使用 languageext 进行应用验证?
how to use applicative validation using languageext?
我正在尝试通过教学库 LaYumba to 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 代码,我需要一些帮助:如何将 "lift" 函数 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
我查看了用于验证的语言扩展测试,并在最后一个函数中复制了 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)
{
}
}
}
我正在尝试通过教学库 LaYumba to 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 代码,我需要一些帮助:如何将 "lift" 函数 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
我查看了用于验证的语言扩展测试,并在最后一个函数中复制了 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)
{
}
}
}