Search code examples
scalagenericstypeclassimplicitcontext-bound

No implicit Ordering defined for ord


I want to define a collection class and require its element being Ordered

Considering the code below:

class MyCollection[K: Ordered[K]] {
  def func(seq: Seq[K]): Unit = {
    seq.sorted
  }
}

The compiler will report error No implicit Ordering defined for ord: Ordering[K]

Am I doing anything wrong? Given that we already have the constraint K: Ordered[K]


Solution

  • You should use:

    • either Ordered with

      • F-bound

        class MyCollection[K <: Ordered[K]] {
          def func(seq: Seq[K]): Unit =
            seq.sorted
        }
        
      • generalized constraint

        class MyCollection[K](implicit ev: K <:< Ordered[K]) {
          def func(seq: Seq[K]): Unit =
            seq.sorted
        }
        
      • view bound

        class MyCollection[K](implicit ev: K => Ordered[K]) {
          def func(seq: Seq[K]): Unit =
            seq.sorted
        }
        

        (from stronger to weaker assumption)

    • or Ordering with context bound

      class MyCollection[K: Ordering] {
        def func(seq: Seq[K]): Unit =
          seq.sorted
      }
      

    Ordered and Ordering are now defined so that the constraints K => Ordered[K] and K: Ordering are actually equivalent. Indeed, Ordering.ordered transforms one into another in one direction, Ordered.orderingToOrdered transforms in the other

    def test[K](implicit ev: K => Ordered[K]) =
      implicitly[Ordering[K]] // compiles
    
    def test[K: Ordering] =
      implicitly[K => Ordered[K]] // compiles
    

    The context bound MyCollection[K: Ordering] is a syntax sugar for MyCollection[K](implicit ev: Ordering[K]). That's why [K: Ordered[K]] can't compile at all because of kind mismatch.

    Ordering is a type class but Ordered is not. Ordered is an ordinary OOP trait (you're extending it in OOP style rather than define its implicit instances in FP style). That's why although [K: Ordered] compiles but it would be incorrect semantically (implicits will not be found).

    Ordering and Ordered and comparing Options

    Scala Ordering, Ordered, and View Bound

    Get Ordering from Ordered in Scala