Search code examples
scalaseqcontext-bound

Scala context bound unexpectedly not working


I tried to define a function that would check whether a generic Seq is sorted.

I came up with this:

import Ordering.Implicits._

def isOrdered[A: Ordering](seq: Seq[A]): Boolean =
  seq.sliding(2).map({ case List(a, b) => b > a }).forall(identity)

At which point, the compiler throws back "No implicit Ordering defined for A".

I can work around this by ascribing a and b as follows:

def isOrdered[A: Ordering](seq: Seq[A]): Boolean =
  seq.sliding(2).map({ case List(a: A, b: A) => a < b }).forall(identity)

At which point the compiler happily accepts the function.

What I find curious is that the following implementation works out of the box:

def isOrdered[A: Ordering](seq: Seq[A]): Boolean =
  seq.sliding(2).exists{s => s(0) > s(1)}

Where as far as I can tell, the only significant difference is that I don't use a partial function.

Can anyone explain this behavior?


Solution

  • In the first case,

    { case List(a, b) => b > a }
    

    This doesn't work because you have just defined a partial function but not the Ordering of those elements. In the sense case List(a,b) represents a List containing a and b. Now a can mean anything. Doing a:A, b:A works because now you define that it is a List containing 2 elements of type A.

    And because we have defined Ordering for A. Hence the second works.

    As per the third one: seq.sliding(2). returns a Iterator[List[A]]. For each List[A] in the iterator, you are calling s(0) > s(1). Here s(0) and s(1) is of type A. Because you have defined the bound A: Ordering, you have ordering defined for type A. In this case s(0) s(1). Hence it works.