何时以及为什么应该在 Scala 中使用 Applicative Functors

2024-03-06

我知道Monad在Scala中可以表示如下:

trait Monad[F[_]] {
  def flatMap[A, B](f: A => F[B]): F[A] => F[B]
}

我明白为什么它很有用了。例如,给定两个函数:

getUserById(userId: Int): Option[User] = ...
getPhone(user: User): Option[Phone] = ...

我可以轻松编写函数getPhoneByUserId(userId: Int) since Option是一个单子:

def getPhoneByUserId(userId: Int): Option[Phone] = 
  getUserById(userId).flatMap(user => getPhone(user))

...

现在我明白了Applicative Functor在斯卡拉中:

trait Applicative[F[_]] {
  def apply[A, B](f: F[A => B]): F[A] => F[B]
}

我想知道什么时候应该使用它代替单子。我想选项和列表都是Applicatives。你能给出简单的使用例子吗apply带有选项和列表并解释why我应该用它代替 flatMap ?


To 引用我自己的话 https://stackoverflow.com/a/12309023/334519:

那么,当我们有了 monad 时,为什么还要费心应用函子呢? 首先,根本不可能提供 monad 实例 我们想要使用的一些抽象——Validation是个 完美的例子。

其次(相关地),这只是一个可靠的开发实践 完成工作的最弱的抽象。在 原则上这可能允许优化,否则不会 可能,但更重要的是它使我们编写的代码更多 可重复使用的。

对第一段进行一些扩展:有时您无法在单子代码和应用代码之间进行选择。查看其余部分那个答案 https://stackoverflow.com/a/12309023/334519讨论为什么您可能想要使用 ScalazValidation(没有也不可能有 monad 实例)来建模 验证。

关于优化点:可能需要一段时间才能在 Scala 或 Scalaz 中普遍相关,但请参见示例Haskell 的文档Data.Binary http://hackage.haskell.org/package/binary-0.7.1.0/docs/Data-Binary-Get.html:

应用风格有时可以产生更快的代码,例如binary将尝试通过将读取分组在一起来优化代码。

编写应用代码可以让您避免对计算之间的依赖关系做出不必要的声明——类似的单子代码会让您做出这样的声明。足够智能的库或编译器could原则上利用这一事实。

为了使这个想法更加具体,请考虑以下一元代码:

case class Foo(s: Symbol, n: Int)

val maybeFoo = for {
  s <- maybeComputeS(whatever)
  n <- maybeComputeN(whatever)
} yield Foo(s, n)

The for- 理解脱糖或多或少类似于以下内容:

val maybeFoo = maybeComputeS(whatever).flatMap(
  s => maybeComputeN(whatever).map(n => Foo(s, n))
)

我们知道maybeComputeN(whatever)不依赖于s(假设这些是行为良好的方法,不会在幕后改变某些可变状态),但编译器不会——从它的角度来看,它需要知道s在开始计算之前n.

应用版本(使用 Scalaz)如下所示:

val maybeFoo = (maybeComputeS(whatever) |@| maybeComputeN(whatever))(Foo(_, _))

在这里,我们明确指出这两个计算之间不存在依赖关系。

(是的,这个|@|语法非常糟糕——参见这篇博文 http://meta.plasm.us/posts/2013/06/05/applicative-validation-syntax/进行一些讨论和替代方案。)

不过,最后一点确实是最重要的。挑选least能够解决你的问题的强大工具是一个非常强大的原则。有时你确实需要单子组合——在你的getPhoneByUserId例如,方法,但通常你不这样做。

遗憾的是,Haskell 和 Scala 目前都使使用 monad 比使用应用函子方便得多(语法上等),但这主要是历史偶然的问题,并且像这样的发展成语括号 https://github.com/aztek/scala-workflow/是朝着正确方向迈出的一步。

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

何时以及为什么应该在 Scala 中使用 Applicative Functors 的相关文章

随机推荐

  • 指定 ValidationGroup 时 ValidationSummary 不起作用

    我在 ASP NET 页面中有几个部分 需要单独验证它们 每个部分都有自己的验证摘要部分 因此我考虑使用验证摘要 http www w3schools com aspnet control validationsummary asp标签与V
  • 锂充多款车型一览

    假设我有一个实体模型 它是人员和组织模型的基础 我有三个空集合 一个用于实体 一个用于人员 一个用于组织 让我们假设出于这个问题的目的 人员和组织之间的关系将被忽略 最后 我有一个视图 其中包含所有三个模型的字段 我的问题 我是否创建一个模
  • Wordpress Woocommerce 外部产品 - 单击图像而不是产品页面时,外部链接会在弹出窗口中打开。与单击按钮相同

    任何人都知道如何做到这一点 以便当您单击外部 附属产品的产品存档页面上的图像时 该链接将在弹出窗口中打开 就像您单击图像下方的按钮时一样 目前 当您单击图像时 它会转到产品页面 我到处搜索 但找不到如何做到这一点 如果您想了解我的意思 这是
  • 每 n 个字符分割字符串新列

    假设我有一个像这样的数据框 带有字符串向量 var2 var1 var2 1 abcdefghi 2 abcdefghijklmnop 3 abc 4 abcdefghijklmnopqrst 将 var2 每 n 个字符拆分为新列直到每个
  • 图像大小调整后 OpenCV VideoWriter 不工作

    我正在使用 OpenCV 3 和 Visual Studio 这里的问题是 除了默认的完整相机分辨率之外 我无法保存任何特定分辨率的视频 没有错误 但视频文件不增长 它保持在 5 54kb 这是我的代码 include opencv2 op
  • 在 MongoDB 全文搜索中搜索特定字段中的值

    MongoDB 全文搜索 你好 我已经在索引中放入了一些字段 这就是我可以搜索的方式搜索关键字 BasicDBObject search new BasicDBObject search search keyword BasicDBObje
  • Rails 如何对 Javascript 进行 Gzip 压缩? (赫罗库)

    我已经运行了 google page speed 它说我应该 Gzip 我的 javascript 文件 如何对我的 javascript 文件进行 gzip 压缩 如果有的话 我的网站托管在 heroku 上 您可以使用 jammit g
  • 在RaspberryPi上连接华为E3372

    我尝试使用华为 e3372 的 LTE 棒连接到互联网 我安装了 usb modeswitch ppp 和 wvdial modewswitch 工作正常 该设备安装在 dev ttyUSB0 上 我可以在其中发送 AT 命令 我想使用 w
  • 收到“此应用程序正在从后台线程修改自动布局引擎”错误?

    在我的 OS X 中使用 swift 经常遇到这个错误 此应用程序正在从后台线程修改自动布局引擎 这可能会导致引擎损坏和奇怪的崩溃 这将在未来的版本中导致异常 我有一个我的NSWindow我正在交换观点contentView窗户的 我得到了
  • 当鼠标悬停时,Chartjs 显示标签和单位统计

    当我的鼠标指针悬停在图表上时是否可以显示标签和单位 目前只有数字 对于下面的例子 我想展示 58 标签1 0 标签2 0 标签3 0 标签4 0 标签5 我的选项如下所示 var options Boolean Show a backdro
  • 如何在 Java 代理中包含自行创建的 Java 文件

    In IBM Notes if I create a Java Agent how do I then include my own created java files 所以我创建了一个 cxmlCustom 包 我想将其包含在 prof
  • 如何在android中动态画线[重复]

    这个问题在这里已经有答案了 可能的重复 如何在android中画一条线 https stackoverflow com questions 3616676 how to draw a line in android 我必须匹配两个选项 就像
  • 通过膨胀布局创建自定义视图?

    我正在尝试创建一个自定义视图来替换我在多个地方使用的特定布局 但我正在努力做到这一点 基本上 我想替换这个
  • 带有 LaTeX 文本的参考文献

    在 LaTeX 中 您可以通过使用轻松引用某个部分 label 旁边的一个部分 然后 ref 创建参考 但是 参考文献仅包括节号或带有以下内容的页码 pageref 我想插入包含该部分文本的参考 Example section My Sec
  • 使用C#正则表达式删除HTML标签

    如何使用 C 正则表达式替换 删除所有 HTML 标记 包括尖括号 有人可以帮我解决代码吗 正如前面经常提到的 不应使用正则表达式来处理 XML 或 HTML 文档 它们在处理 HTML 和 XML 文档时表现不佳 因为无法以通用方式表达嵌
  • 相当于 VB.NET 中的 MoveNext

    由于 Recordset MoveNext 函数在 VB NET 中不再可用 在互联网上搜索了很多 我想要一种方法来解决我的问题 使用 MSSQL 刚刚在 SQLDATASET 不支持的地方看到 movenext 函数 我想使用类似于 Mo
  • 当我在线加载页面时,“web.config”文件出错

    我是 ASP NET 4 0 的新手开发人员 我开发了一个网站 它完全可以在我的本地系统中运行 但是现在我将所有文件上传到服务器 当我加载任何页面时 会出现错误网页配置 file 我的 Web Config 代码是这样的
  • Xcode 3.1.4 缺少代码签名权利选项?

    我使用的是 Xcode 3 1 4 并遇到了可怕的 可执行文件已使用无效权利签名 错误 我正在尝试在 BUILD 选项中添加 Entitlement plist 但我找不到放置它的位置 该选项曾经存在于 代码签名身份 之上 我认为它被称为
  • 用于网站流媒体的免费音频播放器

    我可以在我的网站中使用免费的音频播放器吗 它们可以定制吗 我听说过 Soundmanager 2 它是一个基于 Flash 的播放器 带有 JavaScript 前端 还有其他类似的免费播放器吗 如果您想要不需要加载 Flash 插件的东西
  • 何时以及为什么应该在 Scala 中使用 Applicative Functors

    我知道Monad在Scala中可以表示如下 trait Monad F def flatMap A B f A gt F B F A gt F B 我明白为什么它很有用了 例如 给定两个函数 getUserById userId Int O