gpt4 book ai didi

带有多个 from 子句的 Either 的 language-ext 任务

转载 作者:行者123 更新时间:2023-12-02 00:30:01 29 4
gpt4 key购买 nike

我在学习 FP with language-ext 时遇到了一个一直没能克服的问题。我将我的代码简化为这个例子:

using System;
using System.Threading.Tasks;
using LanguageExt;
using static LanguageExt.Prelude;
using Xunit;

namespace Temp {

public class SelectManyError {

[Fact]
public async Task Do() {

var six = await from a in Task.FromResult(Right<Exception, int>(1))
from b in Task.FromResult(Right<Exception, int>(2))
from c in Task.FromResult(Right<Exception, int>(3))
select a + b + c;

}
}
}

我收到这个错误:

Multiple implementations of the query pattern were found for source type Task<Either<Exception, int>>. Ambiguous call to 'SelectMany'.

我从阅读 this webpage 中了解到编译器认为问题出在哪里.但是,我显然遗漏了或不理解一些重要的事情,因为我无法弄清楚这种情况是如何导致这个错误的,也不知道该怎么办。如果它只有 2 个来自子句,这将工作得很好,这让我更加困惑。

这是解决此类问题的错误方法吗?还有其他我不知道的方法吗?

最佳答案

Lang-ext 作者在这里。我们一直在讨论这个问题 lang-ext github repo .

这些是我的评论:

这很艰难。老实说,它们并不是真正的误报,因为Either<L, R>支持+运算符,所以 SelectMany属于 Task<R>将产生一个有效的结果,就像 SelectMany适用于 Task<Either<L, R>> .

基本上是 a , b , 和 c合法的值可以是 intEither<Exception, int>取决于哪个SelectMany编译器选择的实现。

整个表达式对所有 SelectMany 都有效扩展,这显然是我们有歧义的原因。

很遗憾改变var three = ...Either<Exception, int> three = ...不改变推理系统。因为这是编译器混淆的两个可能表达式之间的关键区别。

你可能想做的一件事而不是使用 Task<Option<A>>正在使用OptionAsync<A>而不是 Task<Either<L, R>>使用 EitherAsync<L, R> .它们本质上是完全相同的类型,除了它很好地包装了所有绑定(bind)语义,所以您再也不会遇到这个问题。

我正在经历创建 *Async 的过程lang-ext 中所有单子(monad)类型的变体。为了方便,潜在的性能优势,并允许相当于 3 层嵌套的 monad:M<A<B<C>>>例如 Seq<OptionAsync<A>>Seq<Task<Option<A>>>相同.

无论如何,回到上面的示例,您可以改为:

public async Task<int> Method()
{
var six = from a in Right<Exception, int>(1).ToAsync()
from b in Right<Exception, int>(2).ToAsync()
from c in Right<Exception, int>(3).ToAsync()
select a + b + c;

return await six.IfLeft(0);
}

或者如果你想从 Task<int> 构建:

public async Task<int> Method()
{
var six = from a in RightAsync<Exception, int>(Task.FromResult(1))
from b in RightAsync<Exception, int>(Task.FromResult(2))
from c in RightAsync<Exception, int>(Task.FromResult(3))
select a + b + c;

return await six.IfLeft(0);
}

或者,您可以留在 monad 中并返回:

public EitherAsync<Exception, int> Method() =>
from a in RightAsync<Exception, int>(Task.FromResult(1))
from b in RightAsync<Exception, int>(Task.FromResult(2))
from c in RightAsync<Exception, int>(Task.FromResult(3))
select a + b + c;

关于带有多个 from 子句的 Either 的 language-ext 任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52247863/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com