radai
radai

Reputation: 24192

scala widening of method signatures

I have a class written that expects to be given an Option[(E) => Long]:

class Whatever[E] (sizeFunction: Option[(E) => Long])

When I try and instantiate it with a function (E) => Int:

val sizeFunction = (a: String) => a.length
new Whatever[String](Some(sizeFunction))

i get a compilation error:

type mismatch;
found   : String => Int
required: String => Long

Shouldnt String => Int "satisfy" String => Long due to widening?

Upvotes: 1

Views: 485

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170805

In Scala, functions are covariant in their return type: for A => B to be a subtype of A => C, B must be a subtype of C. But Int is not a subtype of Long (i.e. it isn't true that "every Int is a Long"); instead it can be widened to Long, which is a different relation.

Definition of covariance probably could be changed to say that B must weakly conform to C instead (i.e. B is a subtype of C, or can be widened to C, or there is a chain of intermediate types between B and C for which one of the above holds). But then for consistency the same would have to apply to contravariance: Long => A would be a subtype of Int => A (by applying widening to the argument). This doesn't seem like a good idea to me (and changing only covariance, but not contravariance, seems even worse).

Upvotes: 2

Scott Shipp
Scott Shipp

Reputation: 2321

Keep in mind String => Int is a type in and of itself. String => Long is a different type. This is important to some programs and not important to others, as in your example. But it would be dangerous for the compiler to make assumptions and not call out type mismatches because it could possibly widen one part of a function type. If you really care you can define sizeFunction as String => Number.

Upvotes: 2

Related Questions