我正在尝试掌握以下文章:Typelevel quicksort in Scala
作者在一开始就介绍了类型级自然数:
sealed trait Nat
final class _0 extends Nat
final class Succ[P <: Nat]() extends Nat
trait Sum[A <: Nat, B <: Nat] { type Out <: Nat }
object Sum {
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Aux[A, B, sum.Out] = sum
type Aux[A <: Nat, B <: Nat, C <: Nat] = Sum[A, B] { type Out = C }
implicit def sum1[B <: Nat]: Aux[_0, B, B] = new Sum[_0, B] { type Out = B }
implicit def sum2[A <: Nat, B <: Nat]
(implicit sum : Sum[A, Succ[B]]): Aux[Succ[A], B, sum.Out] = new Sum[Succ[A], B] { type Out = sum.Out }
}
它的工作方式如下:
scala> :t Sum[Succ[_0], Succ[Succ[_0]]]
Sum[Succ[_0],Succ[Succ[_0]]]{type Out = Succ[Succ[Succ[_0]]]}
以下是我在这种情况下“理解”编译器的工作原理。首先,编译器在伴随对象中找到apply
方法:
Sum.apply[Succ[_0], Succ[Succ[_0]]](implicit sum: Sum[Succ[_0], Succ[Succ[_0]]]):
Aux[Succ[_0], Succ[Succ[_0]], sum.Out] = sum
现在需要找到类型为sum
的隐式参数Sum[Succ[_0], Succ[Succ[_0]]]
。我了解正确的sum2
A = _0
和B = Succ[Succ[_0]]
。
但编译器如何做到这一点?它是否对输出类型执行某种模式匹配,以实现如果_0
为A
它将获得正确的输出类型?最后是否存在这种模式匹配复杂程度的规则?
编辑:“Where does Scala look for implicits?”的答案可以很好地解释编译器在何处以及优先级中寻找隐式定义。我的问题是关于类型推断机制。编译器如何在示例中表示Sum
这样的递归类型?当它的某些部分未知时,它如何与隐式定义的输出类型相匹配?