I had to write a context bound for Ordering[Option[T]]
it turns out that the solution was
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))
}
see How to define a context bound with a higher kinded Type (Type Constructor)
So played with type lambda a little to understand better, leading me to write the version without type lambda:
type L[x] = Ordering[Option[x]]
def testN[T: L](value1: Option[T], value2: Option[T]) = {
implicitly[L[T]].compare(value1, value2)
}
Many example of the use of Type lambda are for type constructor with 2 parameters such MAP[K,V].
In this case we do not have that problem.
So i just wonder, why not having something like this
def test[T: Ordering[Option]](value1: Option[T], value2: Option[T]) = {
val e = implicitly(Ordering[Option[T]].compare(value1, value2))
}
obviously it does not work. I think I understood the all point, there is no type constructor Ordering[Option[_]]
defined.
What we have in ordering is:
trait OptionOrdering[T] extends Ordering[Option[T]] {
def optionOrdering: Ordering[T]
def compare(x: Option[T], y: Option[T]) = (x, y) match {
case (None, None) => 0
case (None, _) => -1
case (_, None) => 1
case (Some(x), Some(y)) => optionOrdering.compare(x, y)
}
}
implicit def Option[T](implicit ord: Ordering[T]): Ordering[Option[T]] =
new OptionOrdering[T] { val optionOrdering = ord }
As it stands Ordering[Option[T]]
in the definition above, is Ordering[Option[T]] forSome {type T}
akka Existential, therefore a proper type, and not a type constructor.
So if i am correct what we do here:
({type L[x] = Ordering[Option[x]]})#L
or here:
type L[x] = Ordering[Option[x]]
is defining a Type Constructor Ordering[Option[_]]
.
Question 1:
1 - is my understanding correct ? is that what the Type Lambda does here ?
2 - I'm a bit confused here, so type alias is something that allows you to create type constructor out of the composition of other type constructors. In a sense i am trying to understand the formal role of type alias with type variable.
scala> type e0 = Ordering[Option[_]]
defined type alias e0
scala> :kind -v e0
e0's kind is A
*
This is a proper type.
scala> type e1[w] = Ordering[Option[w]]
defined type alias e1
scala> :kind -v e1
e1's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.
scala>
Anonymous type constructor
is to named type constructor
what anonymous (value) constructor
is to named (value) constructor
for example
In Scala 3 (Dotty) you will be able to replace the "atrocity"
with beautiful type lambda syntax
The context bound syntax
is equivalent to
which simplifies to