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?
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.