7

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.

Noel M
  • 15,812
  • 8
  • 39
  • 47

2 Answers2

6

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.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • The example in the question might only be illustrative, but on the face of it, alphabetical order (which is what shapeless provides) is exactly what's being asked for here ;-) – Miles Sabin Mar 30 '16 at 11:23
  • @MilesSabin Fair enough! That's pretty much the only example I can think of where alphabetical constructor names are what you want, though. :) – Travis Brown Mar 30 '16 at 11:25
2

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..

lloydmeta
  • 1,289
  • 1
  • 15
  • 25