在https://jto.github.io/articles/typelevel_quicksort中:
我们接触到Sum
类似apply
的{{1}}类型:
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Aux[A, B, sum.Out] = sum
现在,我们可以直接使用类型细化而不是Aux,但问题仍然存在:为什么这(显式返回类型)是必要的? apply
的返回类型的Sum#Out类型是否等于sum.Out是不是“显而易见”?
如果我们删除它并且我们只使用val x = Sum[_0, _1]
,它看起来很好,除了添加val y = Sum[x.Out, _1]
不起作用,说编译器找不到隐式Sum。
为什么编译器似乎“忘记”了x.Out的确切类型?
答案 0 :(得分:3)
类型Sum[A, B]
和Sum.Aux[A, B, C] = Sum[A, B] { type Out = C }
不同。后者是前者的亚型。 Sum[A, B]
也是存在类型Sum.Aux[A, B, _]
。
apply
的返回类型不会“显而易见” Sum#Out类型等于sum.Out?
没有
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]) = sum
与
相同def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Sum[A, B] = sum
首先,您要定义隐含:使用sum1
,sum2
进行归纳或简单地
implicit val sum00: Aux[_0, _0, _0] = new Sum[_0, _0] { type Out = _0 }
implicit val sum01: Aux[_0, _1, _1] = new Sum[_0, _1] { type Out = _1 }
implicit val sum10: Aux[_1, _0, _1] = new Sum[_1, _0] { type Out = _1 }
implicit val sum11: Aux[_1, _1, _2] = new Sum[_1, _1] { type Out = _2 }
...
然后当你写
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Aux[A, B, sum.Out] = sum
只知道A
和B
就足以解决隐含问题。每个定义的隐含“知道”其特定的C
。但如果您只返回Sum[A, B]
,则C
会被遗忘。
您可以定义
def apply[A <: Nat, B <: Nat, C <: Nat](implicit sum: Aux[A, B, C]): Aux[A, B, C] = sum
但是您必须手动指定C
:Sum[_2, _3, _5]
。
如果我们删除它并且我们只使用
val x = Sum[_0, _1]
,它看起来很好, 除了添加val y = Sum[x.Out, _1]
将不起作用,说 编译器找不到隐式Sum。
不确定。 x.Out
不再是_1
,它只是一些抽象的x.Out
,隐式无法解析。