How to do ordering of a sealed trait?

I have a distributed system defined by a sort of "state machine" ( "flow chart" )

each system writes there state in a shared "log"

I'm representing each state as part of a sealed trait and a given "status" for that state

I want to "merge/reduce" to a single status which represents the current progress.

(There are some relaxations in place as not all must succeed in order for the final status to complete successfully)

There are 2 sealed traits representing the flow:

sealed trait System
case object A extends System
case object B extends System
case object C extends System

sealed trait Status
case object Pending extends Status
case object InProgress extends Status
case object Success extends Status
case object Fail extends Status


A, Success
B, Fail
C, Pending

now there are a set of rules which I use to define a single status reduction

basically it gives a priority

A < B < C, ... < Z


Pending < InProgress < Success < Fail

so if there is a status of:

(A, Success) versus (C, Pending)

I want to reduce it to (C,Pending)

and if

(A,Success) versus (B, Fail)

I want to reduce it to (B, Fail)

I can model this as a simple integer comparison in my case (possibly with an outlier which I explicitly test for)

I'm not clear how to make the sealed traits comparible/orderable which would make my life way easier

something along these lines is adequate:

def reduce(states: Seq[(System,Status)]) : (System,Status) = {
    states.order... {left.system < right.system) && (a.status < b.status) ... possibly another ordering test ....}.tail // take the last one in the ordering


  • You can define a scala.math.Ordering[Status]:

    object StatusOrdering extends Ordering[Status] {
      def compare(x: Status, y: Status): Int =
        (x, y) match {
          // assuming that the ordering is Pending < InProgress < Success < Fail...
          case (_, _) if (x eq y) => 0
          case (Pending, _) => -1
          case (_, Pending) => 1
          case (InProgress, _) => -1
          case (_, InProgress) => 1
          case (Success, _) => -1
          case (_, Success) => 1
          case _ => 0 // (Fail, Fail)

    In your reduce, you can then

    import StatusOrdering.mkOrderingOps

    and your Status objects will be enriched with < and friends.

    It is also possible to have your trait extend Ordered[Status], which defines a canonical ordering in the trait:

    sealed trait OrderedStatus extends Ordered[OrderedStatus] {
      def compare(that: OrderedStatus): Int =
        (this, that) match {
          case (x, y) if (x eq y) => 0
          case (Qux, _) => -1
          case (_, Qux) => 1
          case (Quux, _) => -1
          case (_, Quux) => 1
          case _ => 0
    case object Qux extends OrderedStatus
    case object Quux extends OrderedStatus
    case object Quuux extends OrderedStatus

    Then you don't have to import mkOrderingOps, but I personally dislike the forward use of the extending case objects in the compare method (and the alternative of a boilerplate compare in each case object is even worse).