David Rawson
David Rawson

Reputation: 21487

How do I explain the difference between fold and foldK?

In the context of a programmer newly learning functional programming and completing the online Scala Exercises for Cats here, the following result seems puzzling:

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")
}

I can follow the example for fold but not for foldK. The documentation for foldK says:

This method is identical to fold, except that we use the universal monoid (MonoidK[G]) to get a Monoid[G[A]] instance.

I don't understand how this difference would cause the behaviour seen above where somehow the third element in the list (Option("three")) is "ignored" for the foldK.

Can someone please explain?

Upvotes: 4

Views: 704

Answers (1)

sarveshseri
sarveshseri

Reputation: 13985

fold uses a Monoid[Option[A]] instance, and cats/kernel/instances/option.scala has following implementation for 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))
        }
    }

But foldK wants a MoinoidK[Option] instance and the answer for this difference is in implementation of combineK for Option,

If your look into cats.instances.OptionInstances, you will find following

  def combineK[A](x: Option[A], y: Option[A]): Option[A] = x orElse y

This should be explain things. I don't know if this is intended or just an overlooked deviation towards in-consistency in cats instances.

Upvotes: 6

Related Questions