If trait is covariant when should extending case class also be covariant

I have two data types:

sealed trait Option[+A]
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]

and

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]

what is the rule? If I make trait covariant when extending it case classes should also be covariant?

They do not have to be, but most people would expect them to be.

Like it would be weird that I couldn’t return a Some[Dog] where a Some[Pet] is expected, especially since I can return Option[Dog] where an Option[Pet] is expected.

However, usually, when you have an ADT like this, you usually forget the cases have their own types and you just think on the main type; so it is weird to have, for example, just a Leaf instead of a Tree. But, still, I would make the cases covariant just in case.

1 Like