Reputation: 24192
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
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
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