Derived Ordering for simple enum?

Hi all :raised_hand_with_fingers_splayed:

When I read the beginning of Type Class Derivation | Scala 3 Language Reference | Scala Documentation, I think to myself that I might be able to do the Scala equivalent of Haskell’s

data RGB = Red | Green | Blue 
  deriving(Eq,Ord,Show)

for Ordering, i.e.

enum RGB derives Ordering:
  case Red, Green, Blue

But that results in “value derived is not a member of object scala.math.Ordering”, so I end up doing this:

enum RGB:
  case Red, Green, Blue

given Ordering[RGB] with
  def compare(x: RGB, y: RGB): Int = x.ordinal compare y.ordinal

import RGB._

assert( List(Green, Red, Blue).sorted == List(Red, Green, Blue) )

Am I missing some trick? :slightly_smiling_face:

Thanks,

Philip

I think the problem here might be that Ordering wants your cases to be like Red(T), Green(T), Blue(T), where T already has an Ordering instance.

1 Like

The reason this isn’t working is that there needs to be some def derived[A]: Ordering[A] = ??? method in the Ordering companion object. Only the name really matters.

1 Like

:raised_hand_with_fingers_splayed: @Katrix

Thanks for taking the time to help.

Unless you are busy with something else, could you elaborate a bit? I mean, does your observation suggest a remedy for the code in question, a way to remove

given Ordering[RGB] with
  def compare(x: RGB, y: RGB): Int = x.ordinal compare y.ordinal

and do something simpler or better instead?

Do you have time to show me the code I could add instead?

If I misunderstand and you are too busy, then thank you anyway for your help.

Philip

It’s not an issue in your code, the standard library needs to be updated to define a derived method on Ordering, but Scala 3 uses the Scala 2.13 standard library which makes this tricky without compiler hacks.

6 Likes

@smarter thank you very much for that :+1:

Apparently extension methods on object Ordering are picked up as well. So one could write

extension (obj: Ordering.type)
  def derived[A]: Ordering[A] = ???
3 Likes

Thanks!

In case anyone is interested in a complete solution for enums, here it is:

/** allow derives Ordering for enums */
extension (obj: Ordering.type) {
  def derived[A <: reflect.Enum]: Ordering[A] = Ordering.by(_.ordinal)
}
3 Likes

Impressive necromancy skills! :joy:

Now when to expect this to arrive in the std. lib where it belongs?

1 Like