0
import scala.language.higherKinds
import cats.Functor
import cats.instances.list._
import cats.instances.function._

val list1 = List(1, 2)

val list2 = Functor[List].map(list1)(i => i + 1)

But things don't work so smoothly for functions,

val f1 = (i: Int) => i.toString
val f2 = (s: String) => s

And we have to resort to type trickery,

scala> type TTT[A] = Int => A
// defined type alias TTT

scala> val ff = Functor[TTT].map(f1)(f2)
// ff: TTT[String] = scala.Function1$$Lambda$607/69160933@3a689738

Well... Is there a more direct way to solve this, as this tends to get very tedious for complex functions.

sarveshseri
  • 13,738
  • 28
  • 47

2 Answers2

4

You can write

val ff = Functor[Int => ?].map(f1)(f2)

if you add addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.7") to build.sbt.

Or you can import functor syntax import cats.syntax.functor._ and then write with type ascription

val ff = (f1: TTT[String]).map(f2)

or with explicit type annotation

val f1: TTT[String] = (i: Int) => i.toString
val ff = f1.map(f2)
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • As per this answer, I would advise using kind-projector if you can. Its fairly standard across functional projects and even if people aren't familiar with it the syntax feels fairly natural/self explanatory – Hugo Firth Sep 13 '18 at 08:12
  • @HugoFirth `kind-projector` looks good. I am not sure if I remember correctly but didn't Erik Osheim decide to transition to Rust few months back ? – sarveshseri Sep 13 '18 at 08:23
  • @SarveshKumarSingh eh? no, I think you have Erik confused with someone else. regardless, `kind-projector` is a cornerstone of the Typelevel ecosystem, so even if Erik were to disappear, `kind-projector` would certainly continue to exist, there are lots of other people in Typelevel. – Seth Tisue Sep 13 '18 at 20:22
0

Why would you summon the type class instance explicitly in the first place? cats includes syntax support for functor, so there's no need for that.

import cats.syntax.functor._
import cats.instances.function._
val mul4 = ((a: Int) => a * 2).map(_ * 2)

In order for this to work, you'll need the -Ypartial-unification compiler flag (scalacOptions += "-Ypartial-unification" if you're using sbt). This flag is likely to be enabled by default in future scala versions.

Matthias Berndt
  • 4,387
  • 1
  • 11
  • 25