如何使用 Language-Ext 将 Task> 绑定到 Either<>

2024-03-15

我有可以请求数据库中保存的卡列表的设备(例如移动电话、支付终端等)。为了安全起见,设备需要对自己进行授权,并在 JWT 令牌中提供其序列号。如果其中任何一项不匹配,我们将拒绝该请求。

感谢最近对相关问题的大量帮助,我现在有两种在类似场景中使用的方法......

static Either<int, string> GetDeviceSerialNumberFromToken() {
  // Get the JWT token from the request header, and extract the device serial number.
  // If the token is invalid or serial number isn't present, we return
  // an error code (int). If the data is all OK, we return the serial
  // number. For simplicity, the latter is used here...
  return "abc123";
}

static async Task<Either<int, Device>> GetDevice(string serialNumber) {
  // Check if we have a device with that serial number, and some other checks
  // As this involves the database, this method is async. Here we simulate that...
  await Task.Delay(10);
  return new Device();
}

这些非常简化,省略了参数等,但这不应该影响问题。

在当前场景中,我实际上不需要设备对象,我只需要知道GetDevice返回它,而不是错误代码。

假设我们通过了这两种方法,然后我想获取卡片列表并将其返回。我有一个足够简单的方法来获取列表......

static async Task<List<Card>> GetCards() {
  // As this involves the database, this method is async. Here we simulate that...
  await Task.Delay(10);
  return new List<Card>();
}

我的目的是以我在其他场景中所做的相同方式将这一切联系在一起......

var cardList = await(
        from deviceSerialNumber in GetDeviceSerialNumberFromToken().ToAsync()
        from _ in GetDevice(deviceSerialNumber).ToAsync()
        from cards in GetCards()
        select cards
);

因为这将是一个Either,我会打电话Match对此,如果前两种方法之一失败,则返回错误代码,但这部分与此问题无关。

我的问题是,这会在调用的行上产生编译器错误GetCards() "无法将类型“System.Threading.Tasks.Task”隐式转换为“LanguageExt.Guard”。"

在我得到答案之后上一个问题 https://stackoverflow.com/a/72875493/706346,我尝试添加ToAsync()如下...

from cards in GetCards().ToAsync()

...但这给出了编译器错误““Task”不包含“ToAsync”的定义,并且最佳扩展方法重载“TaskTryExtensions.ToAsync(Try)”需要“Try”类型的接收器。"

I can't await打电话给GetCards(),因为你只能await此类查询中的第一行。我尝试以错误的方式进行操作,即在检查之前获取数据......

var cardList = await(
        from cards in await GetCards()
        from deviceSerialNumber in GetDeviceSerialNumberFromToken().ToAsync()
        from _ in GetDevice(deviceSerialNumber).ToAsync()
        select cards
);

...但这给出了“编译器错误”找不到源类型“List”的查询模式的实现。未找到“SelectMany”。"

此时我被困住了。像往常一样,我想有一个非常简单的答案,但我看不到。有谁可以提供建议吗?

Thanks


当您使用

from x in foo.ToAsync()
from y in bar.ToAsync()

语法中,所有值必须位于同一个 monad 中。在这里你从GetDeviceSerialNumberFromToken().ToAsync(),这是一个EitherAsync值,因此所有后续值也必须是EitherAsync values.

如果您尝试生成一个,这对您来说会更加明显最小的、可重现的例子 https://stackoverflow.com/help/minimal-reproducible-example。当我使用OP中发布的代码执行此操作时,我没有报告编译器错误,而是报告了这个错误:

' 类型的表达式Task<List<Card>>' 不允许出现在源类型为 ' 的查询表达式的后续 from 子句中EitherAsync<int, <anonymous type: string deviceSerialNumber, Device _>>'。调用“时类型推断失败”SelectMany'

我认为从这条消息中应该可以清楚地看出,您需要找到一种“提升”的方法Task<List<Card>> to EitherAsync<int, List<Card>>.

一种选择是使用右异步 https://louthy.github.io/language-ext/LanguageExt.Core/Monads/Alternative%20Value%20Monads/Either/EitherAsync/index.html#EitherAsync_2_RightAsync_0:

var cardList = await (
    from deviceSerialNumber in GetDeviceSerialNumberFromToken().ToAsync()
    from _ in GetDevice(deviceSerialNumber).ToAsync()
    from cards in EitherAsync<int, List<Card>>.RightAsync(GetCards())
    select cards);

根据我对 LanguageExt 的了解,可能有比这更方便的帮助方法,但这就是它的要点。


确实,事情变得little如果进口的话会更容易LanguageExt.Prelude:

var cardList = await (
    from deviceSerialNumber in GetDeviceSerialNumberFromToken().ToAsync()
    from _ in GetDevice(deviceSerialNumber).ToAsync()
    from cards in RightAsync<int, List<Card>>(GetCards())
    select cards);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Language-Ext 将 Task> 绑定到 Either<> 的相关文章

随机推荐

  • 我可以自动发送短信吗(无需用户批准)

    我对 Android 还很陌生 我正在尝试从 Android 应用程序发送短信 使用 SMS Intent 时 SMS 窗口将打开 用户需要批准 SMS 并发送 有没有办法无需用户确认就自动发送短信 谢谢 利奥尔 您可以使用此方法发送短信
  • cv2.imshow() 在线程中调用时启动但不弹出窗口

    cv2 imshow 在线程中调用时不会弹出窗口 docker中出现了python3的图标 但没有窗口 没有绘图 另外 我需要半双工通信的功能 因此我不能只删除线程 如何正确显示螺纹内的图片 任何回应表示赞赏 背景 MacOS Catali
  • Flash Builder 中的 TODO 任务列表

    Flash Builder 支持任务列表吗 我正在测试 PHP 的 Flash Builder 我可以在 PHP 代码中看到我的 TODO 但在 AS 或 MXML 中看不到 我找到了这个插件 http www richinternet d
  • 创建数据模型的最佳实践[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 对于当前的项目 我正在创建一个数据模型 是否有任何来源可以找到良好数据模型的 最佳实践 好的意味着灵活
  • REST 服务的最佳用途是什么?

    我知道像 Facebook 这样的网站现在正在使用 REST 服务 但我想知道其他使用 REST 的应用程序 以及是否存在特定情况下使用 REST 比其他方法更合理 REST 与 CRUD 数据服务无关 是的 您可以使用 REST 来执行类
  • 有没有办法在 PHP 中追溯创建基于时间/节点的 UUID?

    大多数基于时间 类型 1 的 UUID 是使用当前时间创建的 我正在将 MySQL 数据库迁移到 cassandra 并希望为存档项目创建基于时间的 UUID 有人可以提供一个如何使用过去的时间段创建 1 类 UUID 的示例吗 所有 uu
  • 如何发现我创建的物化视图的基础查询?

    我在 Postgres 9 3 中创建了一个物化视图 但此后我丢失了创建它的底层 SELECT 查询 我想删除物化视图 重写查询以包含更多数据 然后创建一个同名但具有新基础查询的物化视图 Just SELECT pg get viewdef
  • 创建键绑定以运行上一个或最后一个 shell 命令

    我经常想快速重新运行我使用的最后一个 shell 命令 我知道您可以将焦点转移到终端 向上箭头并输入 但我认为一定有比这三个步骤更好的方法 The sendSequencevscode 中的命令变得越来越强大 因此我寻找一种方法来创建一个可
  • 有没有一种简单的方法可以将 vulture 与 django 一起使用?

    我正在尝试清理 django 中一些混乱的遗留代码 Vulture http pypi python org pypi vulture看起来是一个不错的选择 但它似乎不知道如何查找 urls py 引用的视图函数 这并不奇怪 因为大多数函数
  • HTML 中的 valign 与 text-align

    我无法通过以下代码找出 HTML 中 valign 与 text align 之间的区别 table width 500 border 0 tr td style background color FFA500 h1 Main Title
  • 在解组操作期间将 nil="true" 转换为 null

    我从服务器接收 XML 该服务器的架构将几乎每个元素指定为
  • Java:jsr166y Phaser 的教程/说明

    这个问题 https stackoverflow com questions 1148125 resources on the upcoming fork join framework两年前被问到 但它提到的资源要么不是很有帮助 恕我直言
  • kivy 应用程序内的一个简单网页作为小部件

    我想在 ubuntu 64 位上运行的 kivy 应用程序中有一个 Web 视图 我查看了网络 浏览了 kivy 的文档并在 StackOverflow 上搜索答案 但我找不到任何可以完成我的工作的东西 一个简单的网页需要在 kivy 应用
  • 可以检测元素的样式是否只是浏览器默认样式还是由样式表或内联样式设置吗?

    我的 javascript 包含在 X 的网站中 但我对她的网站或她包含它的位置没有任何其他控制权 如果她的造型 element 我想不管它 但如果她没有 我有一个样式表 我会注入 有什么办法可以检测她是否有造型吗 检查它的高度是 0 还是
  • 如何用Go实现BitSet?

    我在Go中没有找到BitSet包 所以我尝试实现它 我想使用 uint64 数组来存储这些位 我需要分配 uint64 数组的位数 使用 Java 我可以定义一个采用整数的构造函数 虽然 Go 不提供构造函数 但我如何正确初始化 当用户调用
  • 交换 css 字体时是否会发出 js 事件?

    我可以判断字体何时已成功 或以其他方式 加载 然后使用 JS 进行操作吗 Context 我正在使用 playwright 打印一系列文档 我目前正在加载这些字体https fonts googleapis com css2 family
  • 理解 Java 中抽象类的用途

    假设我有两个类 A和B A类被定义为抽象类 而B类扩展了这个抽象类 最后我测试结果 这两个类都是同一个包的一部分 public abstract class A protected abstract void method1 protect
  • 游标与 While 循环 - SQL Server

    假设我在数据库 本例中为 SQL Server 2008 中有一堆可用于创建方程的行 OperationID EquationID Operation Amount Order 1 1 12 1 2 1 12 2 3 2 2
  • Kubernetes 将 env 变量传递给“kubectl create”

    我需要将动态环境变量传递给kubectl create 像这样的东西 kubectl create f app yaml Target prod 基于Target的代码部署在不同的服务器上 如果您想避免安装第 3 方插件 则可以使用 sed
  • 如何使用 Language-Ext 将 Task> 绑定到 Either<>

    我有可以请求数据库中保存的卡列表的设备 例如移动电话 支付终端等 为了安全起见 设备需要对自己进行授权 并在 JWT 令牌中提供其序列号 如果其中任何一项不匹配 我们将拒绝该请求 感谢最近对相关问题的大量帮助 我现在有两种在类似场景中使用的