为什么具有 Monad 实例的类型的 Semigroupal 不组合?

2024-01-09

我正在尝试研究《猫》中的半群。以下是 Underscore 的“Scala with Cats”中的声明。

cats.Semigroupal是一个类型类,允许我们组合上下文

trait Semigroupal[F[_]] {
  def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}

参数fa and fb彼此独立:我们可以在将它们传递给之前以任一顺序计算它们product。这与flatMap,它对其参数施加了严格的顺序。

所以基本上,我们应该能够结合两个Either上下文也是如此,但这似乎不起作用:

import cats.instances.either._ 

type ErrorOr[A] = Either[Vector[String], A]

Semigroupal[ErrorOr].product(Left(Vector("Error 1")), Left(Vector("Error 2")))

// res3: ErrorOr[Tuple2[Nothing, Nothing]] = Left(Vector("Error 1"))

如果半群的 USP 是急切地执行独立操作,则必须在传递给product但我们无法得出综合结果。

我们可能期望product应用于Either积累错误而不是快速失败。再次,也许令人惊讶的是,我们发现product实现与以下相同的快速失败行为flatMap.

这是否与具有替代方法能够组合任何相同类型的上下文的原始前提相矛盾?

为了确保语义一致,Cats 的 Monad(扩展了 Semigroupal)提供了乘积的标准定义:map and flatMap.

为什么要实施product按照map and flatMap?这里指的是什么语义?

那么为什么要费心半群呢?答案是我们可以创建有用的数据类型,其中包含 Semigroupal(和 Applicative)实例,但不包含 Monad。这使我们能够以不同的方式实现产品。

这究竟意味着什么?

不幸的是,这本书没有详细介绍这些前提!我也无法在网上找到资源。有人可以解释一下吗? TIA。


所以基本上,我们应该能够组合两个 Either 上下文,但这似乎不起作用:

它起作用了,正如您所看到的结果是有效结果,它进行了类型检查。

半群只是意味着给定一个F[A] and a F[B]它产生一个F[(A, B)]这并不意味着它能够独立评估两者;可能会,但也可能不会。与之相反Monad这确实意味着它需要评估F[A]之前因为要评价F[B]它需要A

这是否与具有替代方法能够组合任何相同类型的上下文的原始前提相矛盾?

并不是真正不同的方法,因为Monad[F] <: Semigroupal[F],您可以随时致电product on any Monad。实现一个函数半群只是意味着它对更多类型开放,但并没有改变每种类型的行为。

为什么要用地图和FlatMap来实现产品?这里指的是什么语义?

TL;博士;一致性:

// https://github.com/typelevel/cats/blob/54b3c2a06ff4b31f3c5f84692b1a8a3fbe5ad310/laws/src/main/scala/cats/laws/FlatMapLaws.scala#L18

def flatMapConsistentApply[A, B](fa: F[A], fab: F[A => B]): IsEq[F[B]] =
  fab.ap(fa) <-> fab.flatMap(f => fa.map(f))

上述定律意味着对于任何F[A]并且对于任何F[A => B]只要存在一个Monad (实际上FlatMap) for F then, fab.ap(fa)是相同的fab.flatMap(f => fa.map(f))

现在,为什么?多种原因:

  • 最常见的一个是最小惊喜原则,如果我有一堆要么我将它们传递给通用函数,无论它是否需要Monad or 适用性我预计它会很快失败,因为这是Either.
  • Liskov,假设我有两个函数f and g, f期望一个适用性 and g a Monad, if g calls f在幕后,我希望调用两者都会返回相同的结果。
  • Any Monad必须是一个适用性,但是累积适用性的版本Either需要一个半群为了Left,而,Monad实例不需要这个。

这究竟意味着什么?

这意味着我们可以定义另一种类型(例如,已验证 https://typelevel.org/cats/datatypes/validated.html)这只会满足适用性法律但不是Monad法律,因此它可以实现累积版本ap


奖金,因为有这种情况,有一个类型Monad但可以实施适用性不需要排序,很常见。这cats创建维护者Parallel https://typelevel.org/cats/typeclasses/parallel.html来代表那个。

所以不要转换你的Eithers into 已验证将它们组合起来使用mapN你可以使用parMapN直接在Eithers.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么具有 Monad 实例的类型的 Semigroupal 不组合? 的相关文章

  • 如何从字符串列中提取数字?

    我的要求是从列中的评论列中检索订单号comment并且总是开始于R 订单号应作为新列添加到表中 输入数据 code id mode location status comment AS SD 101 Airways hyderabad D
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 在 Akka/Scala 中使用带有 future 的 mapTo

    我最近开始使用 Akka Scala 编码 遇到了以下问题 通过范围内的隐式转换 例如 implicit def convertTypeAtoTypeX a TypeA TypeX TypeX just some kinda convers
  • 过滤字符串上的 Spark DataFrame 包含

    我在用火花1 3 0 http spark apache org releases spark release 1 3 0 html and 火花阿夫罗1 0 0 https github com databricks spark avro
  • 如何将 scala 列表转换为 javascript 数组?

    有更简单的方法吗 document ready function var jsArray if scalaList null for id lt scalaList jsArray push id 很简单 如下所示 import play
  • 通用 scala 函数,其输入是变量数量的函数

    我想定义一个函数f需要另一个函数g 我们需要g采取采取n双打 对于某些固定n 并返回一个 Double 函数调用f g 应该返回具体值n 例如 f Math max 2因为 Math sin 具有类型 Double Double gt Do
  • Scala 的代码覆盖率工具 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 更改 build.sbt 自定义任务中的版本

    我在 build sbt 中定义了一个自定义任务 val doSmth taskKey Unit smth doSmth version 1 0 SNAPSHOT 但它不会改变版本 我真正想要的是自定义 sbt 发布任务 它将始终将相同的版
  • 高效序列化案例类

    对于我正在工作的图书馆 我需要提供一个高效 便捷 typesafe序列化 scala 类的方法 理想的情况是用户可以创建一个案例类 并且只要所有成员都是可序列化的 它似乎也应该如此 我准确地知道序列化和反序列化阶段的类型 因此不需要 也不能
  • 可选择将项目添加到 Scala 映射

    我正在寻找这个问题的惯用解决方案 我正在构建一个valScala 不可变 Map 并希望有选择地添加一项或多项 val aMap Map key1 gt value1 key2 gt value2 if condition key3 gt
  • 具有上限的联合类型

    我正在遵循这个问题的公认答案中提出的技术如何定义 类型析取 联合类型 https stackoverflow com questions 3508077 does scala have type disjunction union type
  • 规范化且不可变的数据模型

    Haskell如何解决 规范化不可变数据结构 问题 例如 让我们考虑一个表示前女友 男友的数据结构 data Man Man name String exes Woman data Woman Woman name String exes
  • 为什么用scala写的代码比用java写的慢6倍?

    我不确定我在编写 scala 代码时是否犯了一些错误 问题是 The four adjacent digits in the 1000 digit number that have the greatest product are 9 9
  • Akka-Streams 收集数据(Source -> Flow -> Flow (collect) -> Sink)

    我对 Scala 和 Akka 完全陌生 我有一个简单的 RunnableFlow Source gt Flow do some transformation gt Sink runForeach 现在我想要这样的东西 Source gt
  • 为什么自类型类可以声明类

    我知道 Scala 只能混合特征 这对于依赖注入和蛋糕模式是有意义的 我的问题是为什么我仍然可以声明一个需要另一个 类 但不需要特征的类 Code class C class D self C gt 这仍然编译成功 我认为它应该编译失败 因
  • 如何在 sbt 控制台中加载 scala 文件? [复制]

    这个问题在这里已经有答案了 可能的重复 将 Scala 文件加载到解释器中以使用函数 https stackoverflow com questions 7383436 load scala file into interpreter to
  • Spark 2.2 无法将 df 写入 parquet

    我正在构建一个聚类算法 我需要存储模型以供将来加载 我有一个具有以下架构的数据框 val schema new StructType add StructField uniqueId LongType add StructField tim
  • 如何将 Java 地图转换为在 Scala 中使用?

    我正在开发一个 Scala 程序 该程序调用 Java 库中的函数 处理结果并生成 CSV 有问题的 Java 函数如下所示 Map
  • Scala 和 Python 的通行证

    我想知道 是否有相当于 python 的 pass 表达式 这个想法是编写没有实现的方法签名 并编译它们只是为了对某些库原型的这些签名进行类型检查 我能够使用以下方法模拟这种行为 def pass A A throw new Excepti
  • 如何在不从 DataFrame 转换并访问它的情况下向数据集添加列?

    我知道使用以下方法将新列添加到 Spark 数据集的方法 withColumn and a UDF 它返回一个 DataFrame 我还知道 我们可以将生成的 DataFrame 转换为 DataSet 我的问题是 如果我们仍然遵循传统的

随机推荐

  • Linux 上的 MS SQL Server 通过 PHP 提供非模拟预准备语句支持

    Summary 我正在尝试使用准备好的语句来停止 SQL 注入 但无法找到保证其正常工作所需的支持 Scenario 我在 Linux 上托管一个站点 该站点使用 FreeTDS 版本 0 91 连接到 Microsoft SQL Serv
  • 我什么时候真正需要在 Inno Setup 中使用 ScaleX 和 ScaleY 函数?

    这是文档ScaleX功能 ScaleX https jrsoftware org ishelp topic isxfunc scalex htm 同样的事情是为了ScaleY ScaleY https jrsoftware org ishe
  • Redis 连接池 + Node.js

    Node js 异步 I O 是否需要 Redis 连接池 我看到的大多数 Redis 库都允许您创建客户端连接 但连接池模块并不多 因此我认为它并不那么重要 让我困惑的一件事是 Redis 在一个 Redis 实例中默认有 16 个不同
  • 如何使用 PHP 将 .pdf 文件作为 BLOB 存储到 MySQL 中?

    如何从 PHP 将 pdf 文件作为 BLOB 存储到 MySQL 中 编辑添加 以下代码已过时 无法在 PHP 7 中运行 有关更多详细信息 请参阅答案底部的注释 假设一个由整数 ID 和 blob DATA 列组成的表结构 并假设 My
  • 适用于 x64 的 SQLite3.dll

    从下载sqlite org 下载 https www sqlite org download html 他们提供适用于 Windows 的预编译二进制文件适用于 x86 和 x64 所以 下载的是 def文件和一个 dll文件 使用这两个文
  • 单击侦听器上的通知 RemoteView

    所以 经过一番绞尽脑汁之后 我已经无计可施了 我有一个媒体播放器RemoteViews在我的通知中 我希望能够访问播放 暂停 上一个和下一个按钮 我知道setOnClickPendingIntent 将用于通过通知进行通信 然而 我想知道这
  • 如何从 NSString 中提取/拆分数字和字符串

    我有一个 NSString text randomtext12345 文本字符串始终以 string 未知长度 开头 后跟 number 整数类型 文本之间没有 分隔符 如何检测哪个是字符串还是整数 为了提取 分离 分离出文本成为 NSSt
  • 空节点的非法自关闭节点表示法 - 使用 PHP DOMDocument 输出 XHTML

    我正在 PHP 中使用 XPATH 处理符合 XML 的 XHTML 输入 如下所示 xml new DOMDocument xml gt loadXML utf8 encode temp temp utf8 decode xml gt s
  • 执行到 pod 的 kubernetes RBAC 角色动词

    我的 1 9 集群为开发用户创建了这个部署角色 部署按预期进行 现在我想向开发人员授予执行和日志访问权限 我需要为 pod 添加什么角色 kind Role name deployment manager rules apiGroups e
  • Python del 语句

    Calling delPython 中的变量 这是立即释放分配的内存还是仍在等待垃圾收集器收集 就像在java中一样 显式调用del对何时释放内存没有影响 del 语句不回收内存 它删除引用 从而减少该值的引用计数 如果计数为零 则可以回收
  • 如何在 SonarQube Scanner for Jenkins 中设置 sonar.projectBaseDir?

    我尝试分析 Jenkins 中多模块项目的一个模块SonarQube 扫描仪 https plugins jenkins io sonar插件 2 5 版 不幸的是 Jenkins 选择了错误的模块作为工作目录 在这种特殊情况下 我可以更改
  • 如何测试用户是否选择了要上传的文件?

    在页面上 我有 if empty FILES logo name dossier upload fichier basename FILES logo name taille maxi 100000 taille filesize FILE
  • android.database.sqlite.SQLiteException:没有这样的列

    当我执行此查询时 我得到 android database sqlite SQLiteException 没有这样的列 错误是什么 public Cursor Getupdate String rid throws SQLException
  • JAVA getConstructor 抛出 NoSuchMethodException

    我是JAVA新手 我正在努力学习反射 http tutorials jenkov com java reflection index html 我想获得特定的构造函数 选择示例表单here http tutorials jenkov com
  • 在向上滚动和向下滚动时向菜单添加底部框阴影

    我有一个具有以下 CSS 属性的菜单 header width 100 position fixed z index 9000 overflow auto 因此 根据上面的 CSS 属性 该元素 header 显然无论滚动如何都会保持在顶部
  • 使用 Swift if let 和逻辑 AND 运算符 &&

    我们知道我们可以使用if let语句作为速记来检查可选的 nil 然后展开 但是 我想使用逻辑 AND 运算符将其与另一个表达式结合起来 因此 例如 在这里我进行可选的链接来展开并可选地将我的 rootViewController 向下转换
  • Mixin 与继承

    mixin 和继承有什么区别 mixin 通常与多重继承一起使用 所以 从这个意义上说 没有区别 细节是 mixin 很少作为独立对象有用 例如 假设您有一个名为 ColorAndDimension 的 mixin 它添加了颜色属性以及宽度
  • 如何修改ES6类的构造函数

    我正在尝试使用 ES6 类进行热代码重载 我需要能够修改类的构造函数 而不需要用新的类替换该类 因为其他人可能会引用它 然而 我发现类对象看起来好像有一些对其最初定义的构造函数的内部引用 实例化该类new也不抬头constructor or
  • 保留 x 个文件并删除所有其他文件 - 第二部分

    我之前问过一个问题 如何遍历目录结构并在每个子目录中保留文件的 7 个最新副本 下面的脚本是创建的脚本 它运行良好 但仅适用于 1 个目录 我需要遍历整个目录并在每个子目录中保留 7 个最新文件 为了测试 我在 C Customer 下创建
  • 为什么具有 Monad 实例的类型的 Semigroupal 不组合?

    我正在尝试研究 猫 中的半群 以下是 Underscore 的 Scala with Cats 中的声明 cats Semigroupal是一个类型类 允许我们组合上下文 trait Semigroupal F def product A