我在这里使用了一个愚蠢的简单示例,以避免与真实案例的细节混淆,并提供一个最小的完整示例。只要您引用了
LanguageExt.Core Nuget package
,并添加了以下内容
using
s
using LanguageExt;
using static LanguageExt.Prelude;
想象一下,我有一个API
float
,并返回加倍的平方根。我有以下助手功能。。。
static Either<string, double> Sqrt(double d) =>
d >= 0.0
? Math.Sqrt(d)
: "Error: Negative number";
static Either<string, double> Double(double d) =>
d > 10.0
? "Error: Too big to double"
: 2 * d;
如果成功,我的API端点将返回一个格式为“Result:23.3”的字符串,否则返回一个错误。
我把这些连接在一起如下。。。
public static string Calc(double d) =>
(from res1 in Sqrt(d)
from res2 in Double(res1)
select res2)
.Match(res => $"Result: {res}",
err => err);
这是意料之中的事。显然,我的真实代码会有更多
from
子句比这个多,但我尽量保持简单。
现在,假设(更现实的是)helper函数是
async
,那么我需要修改我的端点,使其看起来像这样。。。
public static async Task<string> Calc(double d) =>
await (from res1 in Sqrt(d).ToAsync()
from res2 in Double(res1).ToAsync()
select res2)
.Match(res => $"Result: {res}",
err => err);
再说一遍,一切都好。
在一边
我从阅读Paul Louth在LanguageExt期刊上的一些代码中获得了上面的编码风格。如果有更好的方法,请随时提出建议。我并不声称自己是这方面的专家。
但是,现在如果出现错误,我想记录它们,发送电子邮件等,所以第二个lambda到
Match
方法需要
异步
。为了避免编译器错误,我需要制作第一个
异步
以及,然后
await
结果。。。
public static async Task<string> CalcAsync2(double d) =>
await await (from res1 in Sqrt(d).ToAsync()
from res2 in Double(res1).ToAsync()
select res2)
.Match(async res => $"Result: {res}",
async err => {
// Log the error, send an email, etc (async);
return err;
});
这开始让人觉得我做这件事完全错了。也许我错了,但等待等待的任务似乎并不正确。
有人能在这里发表评论吗?如果任何一个helper方法返回了
Left
,但如果所有
异步
工作(事实上,尽可能多的工作)是在
从…起
克吕兹,留下lambdas
Math
只需要返回值。