[英]Features of different kinds of path-dependent types in scala
Suppose there is a trait: 假设有一个特征:
trait OuterTrait {
type InnerType
}
Now we can write non-generic function someAlgo
: 现在我们可以写一些非泛型函数
someAlgo
:
def pairToString[S, U](x: S, y: U): String =
"{" + y.toString + " in " + x.toString + "}"
def pairPrintln[S, U](x: S, y: U) {
println(pairToString(x, y))
}
def someAlgo(x: OuterTrait)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
and series of generic functions: 和一系列通用功能:
def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
And one more generic function doesn't compile: 而另一个通用函数不编译:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
It seems that: 1) someAlgo
and someAlgoObjObj
are the most correct functions; 看来:1)
someAlgo
和someAlgoObjObj
是最正确的功能; 2) and there is no sense to use generic function in this example at all. 2)在这个例子中根本没有使用泛型函数的意义。
And I would like to clarify some differences between generic functions above. 我想澄清上面的通用函数之间的一些差异。 Please, correct me, If I make errors.
请纠正我,如果我犯了错误。
So as I understand type T
corresponds to static type of x
(call it X
) or explicit type of generic call (I mean algo[Int]
for instance). 因此,据我所知,类型
T
对应于静态类型的x
(称为X
)或显式类型的通用调用(我的意思是algo[Int]
)。 That's why T#InnerType
corresponds to type in declaration of type X
. 这就是
T#InnerType
对应于X
类型声明中的类型的原因。 But x.InnerType
also corresponds to InnerType
of static type of x
. 但
x.InnerType
也相当于InnerType
静态类型的x
。 Where is the difference? 区别在哪里?
Further... someAlgoObjType
compiles, so it seems that x.InnerType
must be subtype of T#InnerType
. 进一步...
someAlgoObjType
编译,因此似乎x.InnerType
必须是T#InnerType
子类型 。 Then it is OK that someAlgoTypeObj
doesn't compile, since we can't make downcast implicitly. 然后,
someAlgoTypeObj
无法编译,因为我们无法隐式地进行向下转换。 Though we can rewrite last one: 虽然我们可以改写最后一个:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y.asInstanceOf[x.InnerType]
}
UPD1: I found one difference between someAlgoObjObj
and someAlgoTypeType
if use them with explicit type parameter. UPD1:我发现
someAlgoObjObj
和someAlgoTypeType
之间存在一个区别,如果将它们与显式类型参数一起使用。 If we write some class extending OuterTrait
: 如果我们编写一些扩展
OuterTrait
类:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: Int = 5
Then: 然后:
someAlgoObjObj[OuterTrait](x)(y) // OK
and next call doesn't work: 和下一个电话不起作用:
someAlgoTypeType[OuterTrait](x)(y)
T#InnerType
means "A InnerType belonging in some T" while x.InnerType
means "A InnerType belonging in a given x (of type OuterTrait)". T#InnerType
表示“属于某些 T的内部类型”,而x.InnerType
表示“属于给定 x(类型为OuterTrait)的内部类型”。
The key here in understanding these is in some T vs in a given x . 理解这些的关键在于给定x 中的一些T vs。 You can interpret in some as some T but we don't which T instance , meaning that in a two Ts aren't necessarily the same, so, T#InnerType can't be proven to be equal to another T#InnerType.
你可以将某些解释为某些T但我们没有哪个T实例 ,这意味着在两个Ts中不一定相同,因此,T#InnerType不能被证明等于另一个T#InnerType。
Let's analyze the signatures: 我们来分析一下签名:
/* 1 */ def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = ???
/* 2 */ def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = ???
/* 3 */ def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = ???
Now for the forth one: 现在为第四个:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y
The signature reads: given x and InnerType belonging to some T , returns the InnerType belonging to this x . 签名读取:给定属于某些T的 x和InnerType,返回属于此x的InnerType。 But in the implementation, we try to return y, which belongs to a T that's not necessarily the same as x, hence the compiler complains.
但是在实现中,我们尝试返回y,它属于一个不一定与x相同的T,因此编译器会抱怨。
Little note about update . 关于更新的小注释。
someAlgoTypeType[OuterTrait](x)(y)
Failes because your method signature tells that it expects its y
parameter to conform to the type T#InnerType
and your y.type
is Int. Failes,因为你的方法签名告诉它期望它的
y
参数符合T#InnerType
类型,你的y.type
是Int。 To make it work you should change it's type to the following: 要使其工作,您应该将其类型更改为以下内容:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: x.InnerType = 5
Now y
's type satisfies type projection T#InnerType
and someAlgoTypeType[OuterTrait](x)(y)
compiles 现在
y
的类型满足类型投影T#InnerType
和someAlgoTypeType[OuterTrait](x)(y)
编译
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.