Relative scoping for hierarchical ADT arguments

Sorry for being late to the party, but I encountered this little nuisance myself multiple times as well. So i would really welcome a solution. But, if the starting dot cannot be omitted, please drop the whole idea, for it not only looks kind of ugly, but really is conceptually confusing, especially for beginners.

That said, the two places where spelling out companion object members is most annoying are in the (indirect) constructions and its definition, so i would limit the automatic import to those cases.

Furthermore, these automatic imports should for instance only work if they are allowed explicitly in the definition of the companion object. Maybe we can use the keyword export here (if it does not bite other use). This further reduces compatibility problems, the downside being that it will only work for new cases. The original definition can then be written like:

final case class Shape(geometry: Geometry, color: Color) 

object Shape :
  sealed trait Geometry
  export object Geometry { ... }
  sealed trait Color
  export object Color { ... }

and be used as:

val redCircle = Shape(Circle,Red)

in pattern matching, like before and in related methods:

def myCircle(color: Color): Shape = Shape(Circle,color)

but not in unrelated calls:

case class Model(geometry: Shape.Geometry, color: Shape.Color)  // works, spelled out
val model = Model(Circle,Red) // compiler error, not spelled out, no Shape in sight.
1 Like