5

I'm reading Advanced Scala With Cats. I stuck on this example at functor description (page 59):

object FunctorsDemo extends App {

  import cats.instances.function._
  import cats.syntax.functor._

  val func1 = (x: Int) => x.toDouble
  val func2 = (y: Double) => y * 2

  val func3 = func1.map(func2) // wrong line for me

}

In book everything is okay, but I have this exception:

Error:(10, 21) value map is not a member of Int => Double
  val func3 = func1.map(func2)

Can't understand what I'm doing wrong.

Seth Tisue
  • 29,985
  • 11
  • 82
  • 149
faoxis
  • 1,912
  • 5
  • 16
  • 31

2 Answers2

3

Here is one configuration with the exact version numbers for which it works:

build.sbt:

libraryDependencies += "org.typelevel" %% "cats-core" % "1.1.0"
scalaVersion := "2.12.5"
scalacOptions += "-Ypartial-unification"

Code (FunctionIntDoubleFunctor.scala in same directory as build.sbt):

object FunctionIntDoubleFunctor {

  def main(args: Array[String]) {
    import cats.syntax.functor._

    import cats.instances.function._

    val func1 = (x: Int) => x.toDouble
    val func2 = (y: Double) => y * 2


    val func3 = func1.map(func2)
    println(func3(21)) // prints 42.0
  }

}

Ammonite with @ interp.configureCompiler(_.settings.YpartialUnification.value = true) fails miserably on exactly the same code, and I don't know why, so maybe it has something to do with the tools you are using.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
2

You have encountered a bug in Scala's type inference, the partial unification bug.

Add this to your build.sbt:

scalacOptions += "-Ypartial-unification"

There's a good writeup about it here if you're interested: https://gist.github.com/djspiewak/7a81a395c461fd3a09a6941d4cd040f2

Tom
  • 2,214
  • 2
  • 16
  • 28
  • Is it just a guess, or have you actually tested it? Even with `-Ypartial-unification`, it was throwing `diverging implicit expansion for type T starting with method catsKernelCommutativeGroupForFunction1 in trait FunctionInstances` at me, for no apparent reason... A more complete verifiable example, with all the exact versions etc. would be nice. – Andrey Tyukin Sep 16 '18 at 15:43
  • I did test it in intellij, with `println(func3(10))`, which printed `20.0`. – Tom Sep 16 '18 at 15:48
  • Yeah! That helped me. Thank you! – faoxis Sep 16 '18 at 18:44
  • Note that `-Ypartial-unification` will be enabled by default in Scala 2.13. – Seth Tisue Sep 17 '18 at 04:48