THD
THD

Reputation: 13

Scala Polymorphic Function That Would Compile But Would Not Run As Expected

Given following two Scala functions, both compiles as expected.

scala> def toList[A](a: A) = List(a)
toList: [A](a: A)List[A]

scala> def foo[A](f: A => List[A], b: A) = f(b)
foo: [A](f: A => List[A], b: A)List[A]

Yet, when you run it, it gave following error message:

scala> foo(toList, 12)
<console>:14: error: type mismatch;
 found   : Nothing => List[Nothing]
 required: Int => List[Int]
       foo(toList, 12)

Why does Scala think toList function is of Nothing => List[Nothing] instead of Int => List[Int]?

Upvotes: 0

Views: 59

Answers (2)

Mikel San Vicente
Mikel San Vicente

Reputation: 3863

The Scala compiler will try to infer the type parameters of the method, it will look to the parameters defined int he first parenthesis and try to extract the type from them, if it can not it will pick the next parameter group to infer the type, and so on...

The best way to define that function is like this

def foo[A](b: A)(f: A => List[A]) = f(b)

Giving the parameters in this order will allow you to avoid the need of giving some hint to the compliler. You can call this function like this:

foo(2.0d)(toList)

And you will get a List[Double]

If you keep the other order you will need to give a hint to the compiler in order to figure out the type parameter A

foo(toList[Double], 2.0d)

Upvotes: 1

Ramesh Maharjan
Ramesh Maharjan

Reputation: 41957

According how foo is defined, foo(12, toList) is wrong in passing the arguments. Correct way is foo(toList, 12)

Why does Scala think toList function is of Nothing => List[Nothing] instead of Int => List[Int]?

12 is of Int type and since foo is

def foo[A](f: A => List[A], b: A) = f(b)

its expecting A type which is Int for the toList function as well.

If you call foo as foo(toList, 12D) we get following error

<console>:22: error: type mismatch;
 found   : Nothing => List[Nothing]
 required: Double => List[Double]
       foo(toList, 12D)

Its because 12D is Double type and toList is expected to be of Double too.

So the correct way would be

foo(toList[Any], 12)

Upvotes: 1

Related Questions