Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically derived sealed trait/ADT ordering in Scala

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.

like image 281
Noel M Avatar asked Mar 30 '16 09:03

Noel M


2 Answers

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.

like image 102
Travis Brown Avatar answered Sep 28 '22 09:09

Travis Brown


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

like image 44
lloydmeta Avatar answered Sep 28 '22 07:09

lloydmeta