[英]Why do we need to specify a refined type (or its equivalent Aux) for the output of certain type computations?
In https://jto.github.io/articles/typelevel_quicksort : 在https://jto.github.io/articles/typelevel_quicksort中 :
We are exposed to a Sum
type whose apply
looks like this: 我们接触到一个
Sum
类型,其apply
如下所示:
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Aux[A, B, sum.Out] = sum
Now, we could use type refinement directly instead of Aux, but the question remains: why is this (the explicit return type) necessary? 现在,我们可以直接使用类型细化而不是Aux,但问题仍然存在:为什么这(显式返回类型)是必要的? Wouldn't it be "obvious" that the return type of
apply
would have a Sum#Out type equal to sum.Out? apply
的返回类型是否具有等于sum的Sum#Out类型,这是不是“显而易见”.Out?
If we remove it and we just use val x = Sum[_0, _1]
, it looks fine, except adding val y = Sum[x.Out, _1]
will not work, saying the compiler couldn't find the implicit Sum. 如果我们删除它并且我们只使用
val x = Sum[_0, _1]
,它看起来很好,除了添加val y = Sum[x.Out, _1]
将不起作用,说编译器找不到隐式Sum。
How come the compiler seems to "forget" the exact type of x.Out? 为什么编译器似乎“忘记”了x.Out的确切类型?
Types Sum[A, B]
and Sum.Aux[A, B, C] = Sum[A, B] { type Out = C }
are different. 类型
Sum[A, B]
和Sum.Aux[A, B, C] = Sum[A, B] { type Out = C }
是不同的。 The latter is a subtype of the former. 后者是前者的亚型。 Also
Sum[A, B]
is existential type Sum.Aux[A, B, _]
. Sum[A, B]
也是存在类型Sum.Aux[A, B, _]
。
Wouldn't it be "obvious" that the return type of
apply
would have a Sum#Out type equal to sum.Out?apply
的返回类型是否具有等于sum的Sum#Out类型,这是不是“显而易见”.Out?
No, 没有,
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]) = sum
is the same as 是相同的
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Sum[A, B] = sum
The thing is that firstly you define implicits: either inductively with sum1
, sum2
or simply 首先,你要定义
sum2
:要么是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 }
...
Then when you write 然后当你写
def apply[A <: Nat, B <: Nat](implicit sum: Sum[A, B]): Aux[A, B, sum.Out] = sum
knowing just A
and B
is enough for resolving implicit. 只知道
A
和B
足以解决隐式问题。 And every defined implicit "knows" its specific C
. 每个定义的隐含“知道”其特定的
C
But if you return just Sum[A, B]
this C
will be forgotten. 但如果你只返回
Sum[A, B]
这个C
就会被遗忘。
You could define 你可以定义
def apply[A <: Nat, B <: Nat, C <: Nat](implicit sum: Aux[A, B, C]): Aux[A, B, C] = sum
but then you will have to call it specifying C
manually: Sum[_2, _3, _5]
. 但是你必须手动指定
C
: Sum[_2, _3, _5]
。
If we remove it and we just use
val x = Sum[_0, _1]
, it looks fine, except addingval y = Sum[x.Out, _1]
will not work, saying the compiler couldn't find the implicit Sum.如果我们删除它并且我们只使用
val x = Sum[_0, _1]
,它看起来很好,除了添加val y = Sum[x.Out, _1]
将不起作用,说编译器找不到隐式Sum。
Sure. 当然。
x.Out
is no longer _1
, it's just some abstract x.Out
, and implicit can't be resolved. x.Out
不再是_1
,它只是一些抽象的x.Out
,并且隐含无法解析。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.