IEnumerable of Options to Option of IEnumerable



我有一个第三方方法,可以获取 T 的 IEnumerable 并对其进行评估。 我想在我的 LINQ 评估语句(选择,其中...)中引入具有特殊值的选项(选择,其中...),用于需要输入到方法中的值。

对于每个 T 元素,我希望有一个可以返回转换后的元素或错误(将其保留为延迟执行)的方法,如果返回错误,评估应该在那里停止。(从技术上讲,这可以通过抛出异常来实现,但这正是我试图避免使用 Option 的原因)

我想知道这个概念是否可以使用 LINQ 或更普遍的 C# 实现?

如果无法实现,这会导致我用抛出异常完全替换代码中的选项,因为使用带有选项的 API 的客户端可能会出现同样的问题。

总之,这就是我想要实现的目标:

这可能是要实现的一种可能的 mothod 签名:

public Option<IEnumerable<T>,TError> Sequence<T,TError>(IEnumerable<Option<T,TError>> options)

哪:

  • 应将 T 的 IEnumerable 保留为延迟执行

  • 应返回找到的第一个错误

  • 发现错误时应停止

**最终方法需要 IEnumerable 的 T 来评估它(它可能是我无法访问的第三方方法) 而且我不想两次评估IEnumerable

在尝试了一段时间来解决这个问题之后,并且觉得异常应该能够被任何一个monads模仿,我发布了这个问题的一个更具概念性的版本。

谢谢,并且基于 mark 的回答,这也证实了我对"要么与 C#/Java 风格的异常同构"的怀疑。

我能够创建以下实现:

public static class LinqEitherExtension
{
public static IEnumerable<T> UntilException<T,TException>(
this IEnumerable<Option<T,TException>> enumerable, 
Action<TException> errorHandler
)
{
return enumerable
.TakeWhile(e =>
{
e.MatchNone(errorHandler);
return e.HasValue;
})
.SelectMany(e => e.ToEnumerable());
}
}

public class Program
{
static void Main(string[] args)
{
var numbers = new List<int> {1, 2, 3, 4, 5};
ThirdPartyFunction(numbers.Select(CheckNumbers).UntilException(Console.WriteLine));
//returns: 
//1     
//2
//3 is exceptional number.
}
public static Option<int,string> CheckNumbers(int number)
{
return number == 3
? Option.None<int, string>("3 is exceptional number.")
: number.Some<int, string>();
}
//Cannot be accessed/altered
public static void ThirdPartyFunction(IEnumerable<int> numbers)
{
foreach (var number in numbers) Console.WriteLine(number.ToString());
}
}

注意:如果第三方函数在使用枚举后将继续执行副作用(如 Console.WriteLine),这仍然会在抛出异常和使用错误作为返回类型之间留下差距:

  • 抛出异常方法:也不会执行更多的副作用。
  • 任一方法:会让第三方函数完成执行,客户端消费函数的输出可以忽略返回值,但里面发生的任何副作用还是会执行的。

因为我所追求的将完成工作。

最新更新