Determining the order of subtypes in Scala

I am a complete newbie to Scala and Akka and I am teaching the language itself by creating an order book for stock trading. The core of my order book will be two PriorityQueues, one for bids and one for requests.

val bids = new mutable.PriorityQueue[Bid]()(BidOrdering)
val asks = new mutable.PriorityQueue[Ask]()(AskOrdering)

      

My idea - to determine special BidOrdering

and AskOrdering

for those queues to maintain the price and time priority for rates and different types of queries. However, I find it difficult to define the classes Ordering

.

Here's an example (adapted from the scala docs ) that demonstrates the problem more clearly ...

import scala.util.Sorting

case class LimitOrderBid(quantity:Long, limit:Double)
val bids = Array(LimitOrderBid(100, 30.0), LimitOrderBid(10, 32.3), LimitOrderBid(1, 19))

// sort by limit price
object BidOrdering extends Ordering[LimitOrderBid] {
  def compare(a:LimitOrderBid, b:LimitOrderBid) = a.limit compare b.limit
}
Sorting.quickSort(bids)(BidOrdering)

      

The above works for proposals like LimitOrder. However, my problem is that there will be many types in my model Bid

, and I want to define BidOrdering

in such a way that it can be used to order collections of different subtypes Bids

. I think it will look like ...

object BidOrdering extends Ordering[Bid] {
      def compare(first:Bid, second:Bid) = first compare second
    }
}

      

+3


source to share


1 answer


You are on the right track - you just need to describe how to compare different combinations of subtypes. For example:

sealed trait Base
case class Foo(i: Int) extends Base
case class Bar(s: String) extends Base
case class Qux(f: Double) extends Base

object Base {
  implicit object orderingBase extends Ordering[Base] {
    def compare(first: Base, second: Base) = (first, second) match {
      // First describe how to compare pairs of the same type
      case (Foo(i1), Foo(i2)) => i1 compare i2
      case (Bar(s1), Bar(s2)) => s1 compare s2
      case (Qux(f1), Qux(f2)) => f1 compare f2

      // Every Foo precedes any non-Foo
      case (Foo(_), _) => -1
      case (_, Foo(_)) => 1

      // Every Bar precedes any Qux
      case (Bar(_), Qux(_)) => -1
      case (Qux(_), Bar(_)) => 1
    }
  }
}

      

Or (a little more clear and concise):



sealed trait Base
case class Foo(i: Int) extends Base
case class Bar(s: String) extends Base
case class Qux(f: Double) extends Base

object Base {
  implicit val orderingBase: Ordering[Base] = Ordering.fromLessThan {
    // First describe how to compare pairs of the same type
    case (Foo(i1), Foo(i2)) => i1 < i2
    case (Bar(s1), Bar(s2)) => s1 < s2
    case (Qux(f1), Qux(f2)) => f1 < f2

    // Every Foo precedes any non-Foo
    case (Foo(_), _) => true
    case (_, Foo(_)) => false

    // Every Bar precedes any Qux
    case (Bar(_), Qux(_)) => true
    case (Qux(_), Bar(_)) => false
  }
}

      

If your parent type is sealed, you'll get a nice error message if you miss a case.

+1


source







All Articles