I had a similar feeling when trying to convert one of my ADTs (that has methods) to an inner-class-like syntax. I posted about it the other day on the multi-level enum thread. I could perhaps imagine a syntax like the following, which has nothing to do with enums:
sealed trait Json {
def decode[A](using decoder: Decoder[A]): Option[A] = ...
sealed {
case class Bool(value: Boolean) { ... }
case class Array(items: Seq[Json])
case object Null
}
}
We can play around with the keywords, but I think that two things are essential here:
- Using
case class
andcase object
. This would (a) make it clearer that one is actually a class and the other is an object, and (b) allow for other class-def modifiers –final
,private
, etc – to be integrated seamlessly. - Nest / indent the nested ADTs under a certain keyword (not necessarily
sealed
).
I suspect that this would lead to developers using data-only ADT syntax with extension methods (like here) instead of OOP classes. Not to say that this is a bad thing, but just a consideration to be aware of.