2

I have tried the following

def test[Option[T]: Ordering](value1: Option[T], value2: Option[T]) = {
  val e = implicitly(Ordering[Option[T]].compare(value1, value2))
}

but does not work ? Any idea what's the issue ?

EDIT

This of course works

def test[T](value1: Option[T], value2: Option[T]) (implicit ev: Ordering[Option[T]]) = {
  ev.compare(value1, value2)
}
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
MaatDeamon
  • 9,532
  • 9
  • 60
  • 127

2 Answers2

4

If you really insist on using a context bound you can write a type lambda:

def test[T: ({type L[x] = Ordering[Option[x]]})#L](value1: Option[T], value2: Option[T]) = {
  val e = implicitly(Ordering[Option[T]].compare(value1, value2))
}

Or with the kind-projector plugin you should be able to make this a bit cleaner:

def test[T: Lambda[x => Ordering[Option[x]]]](value1: Option[T], value2: Option[T]) = {
  val e = implicitly(Ordering[Option[T]].compare(value1, value2))
}
Jasper-M
  • 14,966
  • 2
  • 26
  • 37
4

When you write def test[Option[T]: Ordering]... the Option doesn't refer to scala.Option, it's a new type parameter (you can denote it Option or F whatever). So

def test[Option[T]: Ordering](value1: Option[T], value2: Option[T]) = {
  val e = implicitly(Ordering[Option[T]].compare(value1, value2))
}

is actually

def test[F[_]: Ordering](value1: F[T], value2: F[T]) = {
  val e = implicitly(Ordering[F[T]].compare(value1, value2))
}

aka

def test[F[_]](value1: F[T], value2: F[T])(implicit ev: Ordering[F]) = {
  val e = implicitly(Ordering[F[T]].compare(value1, value2))
}

This does't compile because T is not defined and Ordering[F] doesn't make sense. What would compile is

def test[F[_], T](value1: F[T], value2: F[T])(implicit ev: Ordering[F[T]]) = {
  val e = implicitly(Ordering[F[T]].compare(value1, value2))
}

I would recomment to switch on scalacOptions += "-Xlint:type-parameter-shadow".

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66