Is it possible to automatically derive order on a sealed trait family in Scala?
For instance, it would be nice to be able to do:
sealed trait Letters
case object A extends Letters
case object B extends Letters
(A < B) == True
This feels like something Shapeless may be able to handle, but I can't see if this currently exists.
I'm assuming you want the ordering to reflect the order of definition, not ordering by the names of the constructors.
This is no where near as fun as you might expect because knownDirectSubclasses
on the ClassSymbol
API returns a set of symbols, not an ordered sequence. I'm not an expert on scalac internals, but according to Eugene Burmako (who is), the signature of knownDirectSubclasses
just reflects what's happening in scalac.
I've been complaining about this for years, by the way, and at various points I've tried things like reading positions off the symbols, but it doesn't really work.
Shapeless's generic machinery has to make a decision here, since it represents sealed traits as coproducts, which order their elements. In order to keep things deterministic, it uses the names of the constructors to order the cases:
// Entering paste mode (ctrl-D to finish)
sealed trait Letters
case object B extends Letters
case object A extends Letters
// Exiting paste mode, now interpreting.
defined trait Letters
defined object B
defined object A
scala> shapeless.Generic[Letters]
res5: shapeless.Generic[Letters]{type Repr = shapeless.:+:[A.type,shapeless.:+:[B.type,shapeless.CNil]]} = anon$macro$45$1@71a11be4
If this is what you want, you're all set—just find a good tutorial on Shapeless-powered generic derivation and work out the details. Unfortunately in most cases it's probably not what you want, though (East
, North
, South
, West
? Blue
, Green
, Red
?), and what you want (definition ordering) doesn't seem to be reasonably possible.
When writing Enumeratum, I came to the same conclusion as Travis, that knownDirectSubclasses
isn't able to provide information about declaration order.
Still though, within the body of a given module, the AST is still ordered (type is List[Tree]
), so that's how I managed to make declaration-based ordering work and offer an indexOf
method. Once you have an ordered sequence of the sealed trait instances, getting an Order
is fairly trivial.
Sorry, this isn't a Shapeless answer..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With