是否有更简单的方式来使用languageext实现这个流水线?

huangapple go评论60阅读模式
英文:

Is there a simpler way to do this pipeline with languageext?

问题

以下是翻译好的代码部分:

我正在尝试理解如何处理将一个“Either”转换为多个“Either”的函数,以及如何将它们合并成单个流。

以下代码将一个字符串转换为多个数字,对每个数字进行平方运算,并忽略任何错误。对于给定的字符串“1,2,Foo,4”,它会输出1,4,16

这段代码有效,但我不明白为什么“Bind(SafeSplit)”返回一个具有我需要解引用的“Right”属性的“EitherData”。

private static void ValidationPipelineVersion()
{
    var result = Right<Exception, string>("1,2,Foo,4")
        .Bind(SafeSplit)
        .Bind(numStrs => numStrs.Right.Select(SafeParse))
        .Rights() // 现在忽略异常
        .Map(num => num * num) // 平方
        .Iter(num => WriteLine(num));
}

private static Either<Exception, string[]> SafeSplit(string str)
{
    try
    {
        return str.Split(",");
    }
    catch (Exception e)
    {
        return e;
    }
}

private static Either<Exception, int> SafeParse(string str)
{
    try
    {
        return int.Parse(str);
    }
    catch (Exception e)
    {
        return e;
    }
}
英文:

I'm trying to grok how to deal with functions that turn one "Either" into many "Either"s and how you then merge those back into a single stream.

The following turns one string into many numbers, squaring each and ignoring any errors. Given "1,2,Foo,4" it writes out 1,4,16.

It works but I don't understand why Bind(SafeSplit) returns an EitherData which has a Right property I need to dereference.

private static void ValidationPipelineVersion()
{
    var result = Right&lt;Exception, string&gt;(&quot;1,2,Foo,4&quot;)
        .Bind(SafeSplit)
        .Bind(numStrs =&gt; numStrs.Right.Select(SafeParse))
        .Rights() // ignore exceptions for now
        .Map(num =&gt; num * num) // Squared
        .Iter(num =&gt; WriteLine(num));
}

private static Either&lt;Exception,string[]&gt; SafeSplit(string str)
{
    try
    {
        return str.Split(&quot;,&quot;);
    }
    catch (Exception e)
    {
        return e;
    }
}

private static Either&lt;Exception,int&gt; SafeParse(string str)
{
    try
    {
        return int.Parse(str);
    }
    catch (Exception e) 
    {
        return e;
    }
}

答案1

得分: 1

我不明白为什么Bind(SafeSplit)会返回一个具有Right属性需要取消引用的EitherData

你不必(实际上,我建议不要这样做),但它能够编译,因为LanguageExt库带有以下签名的Bind重载:

public static IEnumerable<R> Bind<T, R>(
    this IEnumerable<T> self, Func<T, IEnumerable<R>> binder)
{
    return self.BindFast(binder);
}

而且由于Either<L, R>实现了IEnumerable<EitherData<L, R>>,所以OP中的代码可以编译。

不建议这样做的原因是因为Right属性是部分的或不安全的。只要Either对象是Right值,它就可以工作,但类型的整个目的是你很少知道是否是这种情况。

这里有一个可能看起来不太简单但至少更安全的替代表达式:

var result = Right<Exception, string>("1,2,Foo,4")
    .Bind(SafeSplit)
    .Map(numStrs => numStrs
        .Map(SafeParse)
        .Rights()
        .Map(num => num * num) // 平方
        .Iter(WriteLine));

它不尝试从单子中获取值,而是保留了外部的Either容器,并在其中执行所有操作。

英文:

> I don't understand why Bind(SafeSplit) returns an EitherData which has a Right property I need to dereference.

You don't have to (in fact, I'd advise against it), but it compiles because the LanguageExt library comes with a Bind overload with this signature:

public static IEnumerable&lt;R&gt; Bind&lt;T, R&gt;(
    this IEnumerable&lt;T&gt; self, Func&lt;T, IEnumerable&lt;R&gt;&gt; binder)
{
    return self.BindFast(binder);
}

and since Either&lt;L, R&gt; implements IEnumerable&lt;EitherData&lt;L, R&gt;&gt; the code in the OP compiles.

The reason it's not advisable is because the Right property is partial or unsafe. It works as long as the Either object is a Right value, but the whole point of the type is that you rarely know whether or not that's the case.

Here's an alternative expression that may not look much simpler, but at least is safer:

var result = Right&lt;Exception, string&gt;(&quot;1,2,Foo,4&quot;)
    .Bind(SafeSplit)
    .Map(numStrs =&gt; numStrs
        .Map(SafeParse)
        .Rights()
        .Map(num =&gt; num * num) // Square
        .Iter(WriteLine));

Instead of trying to get the value out of the monad, it keeps the outer Either container and performs all actions inside of it.

huangapple
  • 本文由 发表于 2023年6月26日 18:56:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556043.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定