Reputation: 7817
I have this function:
def unpack[T] = (x:Option[T], y:T) => x match { case Some(z) => z; case None => y }
when I call it like this:
unpack(Some(1), 2)
the result is as expected:
res5: Int = 1
But when I call it with something clearly wrong:
unpack(Some("1"), 2)
the result is:
res6: Any = 1
I understand it can't infer the resulting type and it returns an AnyRef/Val
.
But why doesn't it throw an error I clearly specified in the function that both the Option
and the default are of type T
.
Also the function definition clearly states that the result will be of type T
:
unpack: [T]=> (Option[T], T) => T
Upvotes: 2
Views: 121
Reputation: 37435
This is Scala type inference at work. In the given example, it tries to find the common supertype of String
and Int
and that is Any
Consider a deeper type hierarchy:
trait Veggy
object tomato extends Veggy
trait Fruit extends Veggy
trait Orange extends Fruit
trait BloodOrange extends Orange
trait Apple extends Fruit
Then
unpack(Some(tomato), new Orange{}) // Veggy
unpack(Some(new Apple{}), new Orange{}) // Fruit
unpack(Some(new BloodOrange{}), new Orange{}) // Orange
Do you want to ensure that both parameters are of the exact same type? Then you need to tell the compiler that.
One possible way is to say that x
and y
each have a type and that there should be evidence that the two types are the same:
def unpack[T,U <:T ](x:Option[T], y:U)(implicit ev: T =:= U) : T = x match { case Some(z) => z; case None => y }
unpack(Some(new Fruit{}), new Orange{})
<console>:12: error: Cannot prove that Fruit =:= Orange.
unpack(Some(1), 2) // Int = 1
Upvotes: 6