catnip
catnip copied to clipboard
"knownDirectSubclasses observed before subclass" when deriving for sealed trait
Deriving for a case class works great:
@Semi(Show) case class Foo(a: Int)
Derivation for ADT's is a bit brittle though:
@Semi(Show) sealed trait Tree
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
// 👎Could not derive an instance of Show[Tree]
//implicit val _derived_cats_Show: cats.Show[Tree] = cats.derived.semi.show[Tree]
//knownDirectSubclasses of Tree observed before subclass Node registered
//knownDirectSubclasses of Tree observed before subclass Leaf registered
That's a pity—it's the first thing people will try (at least that's what I went for).
Naturally, the same error occurs with direct use of Kittens:
sealed trait Tree
object Tree {
implicit val showTree: Show[Tree] = cats.derived.semi.show
}
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
// 👎Could not derive an instance of Show[A]
//knownDirectSubclasses of Tree observed before subclass Node registered
//knownDirectSubclasses of Tree observed before subclass Leaf registered
Placing the companion object below the subclasses solves the problem:
sealed trait Tree
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
object Tree {
implicit val showTree: Show[Tree] = cats.derived.semi.show
}
// 👍
But the @Semi
annotation only works on the case class itself:
sealed trait Tree
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
@Semi(Show) object Tree
// 👎@Semi can only annotate class, got: ...
How about allowing @Semi
to be placed on the companion?
Adding a bit of docs around this pitfall might also help.
P.s. The first two things I tried failed, but the following alternatives work fine:
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
@Semi(Show) sealed trait Tree
@Semi(Show) sealed trait Tree
object Tree {
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
}
sealed trait Tree
case class Node(nodes: List[Tree]) extends Tree
case class Leaf(label: String) extends Tree
@Semi(Show) object Tree