Type mismatch in a scala cats "functor" operator

Hi all,

I’m trying to figure out the correct syntax to concatenate two functor opertor. This is my code snippet:

  def calcolaFA : Option[String] = {

    val optionValue : Option[Int] = Some(5);
    val result : Option[String] = optionValue.map(item => item + 1).
                                              map(item => item.toString);

    val applicativeValue : Option[String] = optionValue <*> {item : Option[Int] => item.getOrElse(0).toInt + 1} <*> {item : Option[Int] => item.toString};

    println("Il valore di result è: " + result);
    println("Il valore di applicativeValue è: " + applicativeValue);

    return applicativeValue;
  }

And this is the sbt error output:

type mismatch;
[error]  found   : Option[Int] => Int
[error]  required: Option[?]
[error]     val applicativeValue : Option[String] = optionValue <*> {item : Option[Int] => item.getOrElse(0).toInt + 1} <*> {item : Option[Int] => item.toString};

Someone of you is aware of cats and could please help me?

Thank you !

Not sure what you’re trying to accomplish. You are already “concatenating” two Functor operations by chaining the #map() invocations. If you want to concatenate the functions upfront, just compose them - the functor laws guarantee that mapping over f, then over g is equivalent to mapping over g ∘ f.

import cats.syntax.all.*

def f(i: Int): Int = i + 1
def g(i: Int): String = i.toString

val res1 = 5.some.map(f).map(g) // Some("6")
val res2 = 5.some.map(g.compose(f)) // Some("6")

Functor allows to thread a unary function through a single instance of a “context” (e.g. Option). Applicative extends this to threading an n-ary function through n independent instances of a context.

def h(a: Int, b: Int): Int = a + b

val app1 = h.curried.some <*> 3.some <*> 4.some // Some(7)

In Scala, you’ll rarely use the <*> (#ap()) operator, but use the #mapN() convenience function(s) instead.

val app2 = (3.some, 4.some).mapN(h) // Some(7)

Note that Applicative gives you Functor behavior “for free”.

val res3 = f.pure[Option] <*> 5.some // ~ 5.some.map(f)

I recommend the Cats book.

2 Likes