类型 Lambda on context bound 和类型别名的作用

Type Lambda on context bound and the role of type alias

我必须为 Ordering[Option[T]]

编写上下文绑定

事实证明解决方案是

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))
}

所以玩了一点 lambda 类型以更好地理解,导致我编写了没有类型 lambda 的版本:

type L[x] = Ordering[Option[x]]

def testN[T: L](value1: Option[T], value2: Option[T]) = {
  implicitly[L[T]].compare(value1, value2)
}

很多使用 Type lambda 的例子都用于具有 2 个参数的类型构造函数,例如 MAP[K,V]。

在这种情况下我们没有那个问题。

所以我想知道,为什么没有这样的东西

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

显然它不起作用。我想我理解了所有要点,没有定义类型构造函数 Ordering[Option[_]]

我们订购的是:

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 }

在上面的定义中 Ordering[Option[T]]Ordering[Option[T]] forSome {type T} akka Existential,因此是一个正确的类型,而不是类型构造函数。

所以如果我是正确的,我们在这里做的:

({type L[x] = Ordering[Option[x]]})#L

或此处:

type L[x] = Ordering[Option[x]]

正在定义类型构造函数Ordering[Option[_]]

问题 1:

1 - 我的理解正确吗?这就是 Type Lambda 在这里所做的吗?

2 - 我在这里有点困惑,所以类型别名允许您从其他类型构造函数的组合中创建类型构造函数。从某种意义上说,我试图理解类型变量的类型别名的正式作用。

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> 

匿名类型构造函数

({type L[x] = Ordering[Option[x]]})#L

是命名类型构造函数

type L[x] = Ordering[Option[x]]

什么匿名(值)构造函数

(x: Int) => x + 1

是命名(值)构造函数

val f = (x: Int) => x + 1

例如

scala> lazy val v: (({type L[x] = Ordering[Option[x]]})#L)[Int] = ???
lazy val v: scala.math.Ordering[Option[Int]] // unevaluated

scala> lazy val v: L[Int] = ???
lazy val v: L[Int] // unevaluated

scala> lazy val v = ((x: Int) => x + 1)(41)
lazy val v: Int // unevaluated

scala> lazy val v = f(41)
lazy val v: Int // unevaluated

在 Scala 3 (Dotty) 中,您将能够替换 "atrocity"

There's less need for kind projector in dotty anyway because we have native type lambdas instead of the atrocity involving structural types.

具有漂亮的类型 lambda 语法

Starting dotty REPL...
scala> lazy val v: (({type L[x] = Ordering[Option[x]]})#L)[Int] = ???
lazy val v: Ordering[Option[Int]]

scala> lazy val v: ([x] =>> Ordering[Option[x]])[Int] = ???
lazy val v: Ordering[Option[Int]]

上下文绑定语法

def test[T: ({type L[x] = Ordering[Option[x]]})#L](value1: Option[T], value2: Option[T]) = ???

等同于

def test[T](value1: Option[T], value2: Option[T])(implicit ev: (({type L[x] = Ordering[Option[x]]})#L)[T]) = ???

简化为

def test[T](value1: Option[T], value2: Option[T])(implicit ev: Ordering[Option[T]]) = ???