在 C# 中实现 Either 申请时遇到问题

Trouble Implementing Apply for Either in C#

我正在努力 Functional Programming in C# by Enrico Buonanno

我将如何在 C# 中实现 Apply for Either monad?我尝试了以下不进行类型检查的操作:

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

namespace ch8
{
    public class UnitTest1
    {
        [Fact]
        public void Ex1()
        {
            Func<int, int, int> add = (x, y) => x + y;

            var option = Some(add)
              .Apply(3)
              .Apply(2);

            Assert.Equal(Some(5), option);

            var either = Left(add)
              .Apply(3) // does not type check
              .Apply(2);

            Assert.Equal(Left(5), either);
        }
    }

    public static class Ext
    {
        public static Either<L, R> Apply<L, R>(
            this Either<L, Func<R, R>> source, Either<L, R> target)
          => source.Match(
              l => Left(l),
              f => target.Match<Either<L, R>>(
                  l => Left(l),
                  r => Right(f(r))
              ));
    }
}

我收到以下错误:

watch : Started
Build started, please wait...
UnitTest1.cs(22,16): error CS1061: 'Either.Left<Func<int, int, int>>' does not contain a definition for 'Apply' and no extension method 'Apply' accepting afirst argument of type 'Either.Left<Func<int, int, int>>' could be found (are you missing a using directive or an assembly reference?) [/ch8/ch8/ch8.csproj]
UnitTest1.cs(25,26): error CS1503: Argument 1: cannot convert from 'LaYumba.Functional.Either.Left<int>' to 'string' [/ch8/ch8/ch8.csproj]
UnitTest1.cs(25,35): error CS1503: Argument 2: cannot convert from 'LaYumba.Functional.Either<L, R>' to 'string' [/ch8/ch8/ch8.csproj]
watch : Exited with error code 1
watch : Waiting for a file to change before restarting dotnet...

我做错了什么?

我是这本书的技术校对者,所以如果其中有任何错误,那是我的错:) 书中的很多内容都是基于我的库 language-ext 并且显然是函数式编程技术一般。如果您需要,那里有一个完全成熟的 Either 实现。

但是,对于您的示例,您几乎可以肯定(目前无法检查,我在火车上)应该使用 Right(add) 而不是 Left(add) 作为 Right是成功路由,Left是失败路由。

因此您应该断言结果等于 Right(5)

我已经有一段时间没看过这本书了,但我假设 Left returns Either.Left<L> 没有相同的 API作为 'success' 路线。

如果您将 Left(add) 转换为 Either<L, R>,那么您会发现图书馆打开了。

LeftRight 构造函数必须处理 Either 需要两种类型的事实。所以他们在隐式转换为 Either<L, R> 之前创建 Left<L>Right<R> 的中间值 - 这通常会使您不必编写 Left<L, R>(l)Right<L, R>( r), 但有时类型会自己绊倒。

无论如何,等我手边有调试器时,我会仔细看看