如何解释 Fold 和 FoldK 之间的区别?

Dav*_*son 4 scala scala-cats

在一名程序员刚刚学习函数式编程并完成在线 Scala 猫练习的背景,以下结果似乎令人费解:

import cats._
import cats.implicits._

object Foo {

  def main(args: Array[String]): Unit =
    println(Foldable[List].fold(List(None, Option("two"), Option("three"))))
    //Some("twothree")
    println(Foldable[List].foldK(List(None, Option("two"), Option("three"))))
    //Some("two")
}
Run Code Online (Sandbox Code Playgroud)

我可以遵循 for 的示例fold,但不能遵循 for 的示例foldKFoldK 的文档说:

此方法与 Fold 相同,只是我们使用通用幺半群 ( MonoidK[G]) 来获取Monoid[G[A]]实例。

我不明白这种差异如何导致上面看到的行为,其中列表中的第三个元素 ( Option("three")) 被“忽略” foldK

有人可以解释一下吗?

Sar*_*ngh 6

fold使用 Monoid[Option[A]] 实例,并cats/kernel/instances/option.scala具有以下实现 Monoid[Option[A]].combine

def combine(x: Option[A], y: Option[A]): Option[A] =
    x match {
      case None => y
      case Some(a) =>
        y match {
          case None => x
          case Some(b) => Some(A.combine(a, b))
        }
    }
Run Code Online (Sandbox Code Playgroud)

foldK想要一个MoinoidK[Option]实例,而这种差异的答案是combineKfor的实现Option

如果您查看cats.instances.OptionInstances,您会发现以下内容

  def combineK[A](x: Option[A], y: Option[A]): Option[A] = x orElse y
Run Code Online (Sandbox Code Playgroud)

这应该可以解释事情。我不知道这是故意的还是只是被忽视的猫实例不一致的偏差。