OK, so going back to the original example: An api-side export takes us to a bit less verbosity:
// This is real Scala 3.7.4
final case class Shape(geometry : Shape.Geometry, color : Shape.Color)
object Shape:
export Geometry.*, Color.*
sealed trait Geometry
object Geometry:
case object Triangle extends Geometry
case object Rectangle extends Geometry
case object Circle extends Geometry
end Geometry
sealed trait Color
object Color:
case object Red extends Color
case object Green extends Color
case object Blue extends Color
end Color
end Shape
You then can:
val redCircle = Shape(Shape.Circle, Shape.Red)
But we would like to:
val redCircle = Shape(Circle, Red)
The above could be achieved with further exports on top level of the package but then the namespace outside of Shape is “polluted”.
A proposal is that we could achieve this by allowing export in new positions to unlock target-type scope injection:
// this is hypothetical Scala
final case class Shape(geometry : Shape.Geometry, color : Shape.Color)
object Shape:
sealed trait Geometry
object Geometry:
export case object Triangle extends Geometry
export case object Rectangle extends Geometry
export case object Circle extends Geometry
end Geometry
sealed trait Color
object Color:
export case object Red extends Color
export case object Green extends Color
export case object Blue extends Color
end Color
end Shape
The name space is not “polluted” and target-typing-based member selection works outside Shape where Shape stuff is expected like so and the api-designer can make a nice api:
val g: Shape.Geometry = Circle
This possibility would be discoverable in the api-docs by the export modifier. IDE-support could show hints and make completion etc.
@soronpo What do you think about that? Would it solve your original use case?