Say I have a complicated hierarchy of nodes in a tree structure, where certain types of nodes can only have children of certain (possibly many, possibly even including its own type) types.
Say we have a tree of employees and want to encode which types of employees can be bosses which other types.
One way is to define our Employee
types, President
, CTO
, Manager
, and their corresponding "Subordinate" types, PresidentSubordinate
, CTOSubordinate
, ManagerSubordinate
. Then you could just extend *Subordinate
on any Employee
that they can be bosses of. Then you could do something like this:
sealed trait Employee
sealed trait PresidentSubordinate extends Employee
sealed trait VicePresidentSubordinate extends Employee
sealed trait CTOSubordinate extends Employee
sealed trait ManagerSubordinate extends Employee
sealed trait DeveloperSubordinate extends Employee
case class President(subordinates: Seq[PresidentSubordinate])
case class VicePresident(subordinates: Seq[VicePresidentSubordinates])
extends PresidentSubordinate
case class CTO(subordinates: Seq[CTOSubordinate])
extends PresidentSubordinate
with VicePresidentSubordinate
case class Manager(subordinates: Seq[ManagerSubordinate])
extends VicePresidentSubordinate
case class Developer(subordinates: Seq[DeveloperSubordinate])
extends CTOSubordinate
with ManagerSubordinate
with VicePresidentSubordinate
with DeveloperSubordinate // Devs can be bosses of other devs
// Note, not all employees have subordinates, no need for corresponding type
case class DeveloperIntern()
extends ManagerSubordinate
with DeveloperSubordinate
This approach has worked out well for my half-dozen or so tree node types, but I don't know if this is the best approach as the number of types grows to 10, or 50 types. Maybe there is a much simpler solution, possibly it would be appropriate to use the pattern shown here. Something like
class VicePresidentSubordinate[T <: Employee]
object VicePresidentSubordinate {
implicit object CTOWitness extends VicePresidentSubordinate[CTO]
implicit object ManagerWitness extends VicePresidentSubordinate[Manager]
implicit object DeveloperWitness extends VicePresidentSubordinate[Developer]
}
But then I'm not sure what the resulting case classes would look like, as this obviously doesn't compile:
case class VicePresident(subordinates: Seq[VicePresidentSubordinate]) extends Employee
Thanks for the help!