[英]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)
}
使用類型 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}
阿卡生存,因此一個適當的類型,而不是一個類型構造函數。
所以如果我是正確的,我們在這里做什么:
({type L[x] = Ordering[Option[x]]})#L
或在這里:
type L[x] = Ordering[Option[x]]
正在定義類型構造函數Ordering[Option[_]]
。
問題 1:
1 - 我的理解正確嗎? 這就是類型 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) 中,您將能夠替換“暴行”
無論如何,對 dotty 中的 kind 投影儀的需求較少,因為我們有原生類型的 lambdas 而不是涉及結構類型的暴行。
使用漂亮的類型 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]]) = ???
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.