繁体   English   中英

scala中不同类型的路径依赖类型的特征

[英]Features of different kinds of path-dependent types in scala

假设有一个特征:

trait OuterTrait {
  type InnerType
}

现在我们可以写一些非泛型函数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
}

和一系列通用功能:

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
}

而另一个通用函数不编译:

def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
  pairPrintln(x, y)
  y
}

看来:1) someAlgosomeAlgoObjObj是最正确的功能; 2)在这个例子中根本没有使用泛型函数的意义。

我想澄清上面的通用函数之间的一些差异。 请纠正我,如果我犯了错误。

因此,据我所知,类型T对应于静态类型的x (称为X )或显式类型的通用调用(我的意思是algo[Int] )。 这就是T#InnerType对应于X类型声明中的类型的原因。 x.InnerType也相当于InnerType 静态类型的x 区别在哪里?

进一步... someAlgoObjType编译,因此似乎x.InnerType必须是T#InnerType 子类型 然后, someAlgoTypeObj无法编译,因为我们无法隐式地进行向下转换。 虽然我们可以改写最后一个:

def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
  pairPrintln(x, y)
  y.asInstanceOf[x.InnerType]
}

UPD1:我发现someAlgoObjObjsomeAlgoTypeType之间存在一个区别,如果将它们与显式类型参数一起使用。 如果我们编写一些扩展OuterTrait类:

class OuterIntClass extends OuterTrait{
  type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: Int = 5

然后:

someAlgoObjObj[OuterTrait](x)(y) // OK

和下一个电话不起作用:

someAlgoTypeType[OuterTrait](x)(y)

T#InnerType表示“属于某些 T的内部类型”,而x.InnerType表示“属于给定 x(类型为OuterTrait)的内部类型”。

理解这些的关键在于给定x 中的一些T vs。 你可以将某些解释为某些T但我们没有哪个T实例 ,这意味着在两个Ts中不一定相同,因此,T#InnerType不能被证明等于另一个T#InnerType。

我们来分析一下签名:

/* 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 = ???
  1. 给定x和属于此x的InnerType返回其InnerType。
  2. 给定x和属于此x的 InnerType返回属于某个T的 InnerType,意味着某个T不一定是与x相同的实例。
  3. 给定属于某些T的 x和InnerType返回属于某些T的 InnerType

现在为第四个:

def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y

签名读取:给定属于某些T的 x和InnerType,返回属于此x的InnerType。 但是在实现中,我们尝试返回y,它属于一个不一定与x相同的T,因此编译器会抱怨。

关于更新的小注释。

someAlgoTypeType[OuterTrait](x)(y) 

Failes,因为你的方法签名告诉它期望它的y参数符合T#InnerType类型,你的y.type是Int。 要使其工作,您应该将其类型更改为以下内容:

class OuterIntClass extends OuterTrait{
  type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: x.InnerType = 5

现在y的类型满足类型投影T#InnerTypesomeAlgoTypeType[OuterTrait](x)(y)编译

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM