Reputation: 34061
I have following trait:
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
Then I define a variable with type Branch
:
val t = Branch(Branch(Leaf("S"), Leaf(2)), Leaf(99))
The code above works fine. But when I change it to:
val t = Branch[Int](Branch(Leaf("S"), Leaf(2)), Leaf(99))
The compiler complains:
Error:(41, 37) type mismatch;
found : String("S")
required: Int
val t = Branch[Int](Branch(Leaf("S"), Leaf(2)), Leaf(99))
When I determine the type on the first Branch
(In this case is Int) then the nodes will inherent from parent?
Upvotes: 0
Views: 469
Reputation: 2480
What happens here is that in the case of Branch(Leaf("S"), Leaf(2))
the compiler will try to find a common type. In the case of Int
and String
, their supertype will be Any
.
The problem is you are forcing the type in the branch definition using Branch[Int]
which is invalidated by the contained Branch[Any]
. Removing the [Int]
will fix the compile error but you'll end up having as a result a Branch[Any]
.
Let's breakdown a bit your definition:
sealed trait Tree[+A]
The +
here says that type A
can be covariant. I won't get into details about variance as there are lots of good articles explaining it (e.g. here). Basically it means that a if String
is a subtype of Any
then a Tree[String]
will be a subtype of Tree[Any]
.
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
Let's first notice how A
appears both in the left tree and in the right tree. So what happens when we take two trees that have different types and put them in the same branch?
val left = Leaf(1) // Tree[Int]
val right = Leaf("a") // Tree[String]
val tree = Branch(left, right) // Tree[???]
Since A
has to be the same in the left
and right
values (that's how we defined it), the compiler tries to solve this. So it asks itself: what is the first common type of Int
and String
?
Any
^
/ \
/ \
/ \
AnyVal AnyRef
/ \
Int String
\ /
...
This is the type hierarchy in Scala quite simplified. It's better illustrated here. Thus, the common supertype of String
and Int
is Any
and that's why the your tree will be a Tree[Any]
.
Upvotes: 4