【问题标题】:Sequencing functions with multiple arguments in Cats在 Cats 中对具有多个参数的函数进行排序
【发布时间】:2021-06-12 17:53:56
【问题描述】:

我正在浏览 Underscore 的“Scala with Cats”,偶然发现了以下语句:

Cats 提供了一个 cats.syntax.apply 模块,该模块利用 SemigroupalFunctor 允许用户对具有多个参数的函数进行排序。

据我了解,我们只能对具有单个参数的函数进行排序,因为函数只能返回单个值。

  import cats.implicits._

  val f1: Int => Int = x => x + 1
  val f2: Int => Int = x => x * 4
  val f3: Int => String = x => s"x = $x"

  f1.map(f2).map(f3)(5)

对于以下示例,它表示:在内部 mapN 使用 SemigroupalOptionFunctor 中提取值以将值应用于函数。

final case class Cat(name: String, born: Int, color: String)

(
  Option("Garfield"),
  Option(1978),
  Option("Orange & black")
).mapN(Cat.apply)

// res10: Option[Cat] = Some(Cat("Garfield", 1978, "Orange & black"))

这里Cat.apply 确实是一个具有多个参数的函数,但它被链接到一个函数,该函数本身返回一个选项元组,即单个值。我们可以让它接受多个参数,如下所示:

  final case class Cat(name: String, born: Int, color: String)

  val f: (String, Int, String) => (Option[String], Option[Int], Option[String]) =
    (name, year, color) => (Option(name), Option(year), Option(color))

  f("Garfield", 1978, "Orange & black").mapN(Cat.apply)

现在我们有了函数fCat.apply,它们接受多个参数并链接在一起。是不是上面的声明所指的?但是我似乎无法找到进一步链接更多功能的方法。该语句是否适用于仅在一个级别链接多个参数函数?另外,请注意这里的函数f 与上面描述的单参数函数链接示例相比被急切地应用。这里可以懒惰地应用函数吗?

我在互联网上的 Semigroupal 的任何地方都找不到太多解释。任何人都可以用一个例子来解释这个陈述吗? TIA。

【问题讨论】:

    标签: scala scala-cats


    【解决方案1】:

    但我似乎无法找到进一步链接更多功能的方法。

    我认为我们可以,因为我们可以继续映射例如上下文

    f("Garfield", 1978, "Orange & black")
      .mapN(Cat.apply)
      .map(_.name) // here is another step in the chain of operations
    

    mapN是幕后产品+地图;我们可以像这样显示组成图

    f("Garfield", 1978, "Orange & black")
      .tupled
      .map { case (a, b, c) => Cat.apply(a, b, c) }
      .map { _.name }
    

    tupled 扩展方法最终调用Semigroupal#product

    当他们说

    ...允许用户使用多个参数对函数进行排序。

    我的解释不是我们只用mapN 继续链接,而是我们可以继续在函子的一般意义上链接上下文,如果在链中的某个点,通常是开始,我们有多个相同类型的多个上下文中的值,然后半群+仿函数允许我们连接单个上下文中的值并继续链接。

    另外,请注意,与上面描述的单参数函数链接示例相比,函数 f 被急切地应用。这里可以懒惰地应用函数吗?

    这是 Semigroupal 对 Monad 的主要卖点,即能够“急切地”执行 独立 操作,将结果值连接到上下文中,然后继续链接。使用一元链,即使操作是独立的,一个仍然需要等待另一个才能继续链。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-19
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    • 2017-08-25
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多