簡體   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