2015-07-01 53 views
4

這是一個簡化的情況下,和我完全打開到一個不同的/更好的方式來實現這一點證明嵌套路徑依賴類型的成員的等價

trait Container { 
    type T 
    def data: List[T] 
} 

trait Transform { 
    val from: Container 
    val to: Container 
    def xform: from.T => to.T 
} 

case class Identity(c: Container) extends Transform { 
    val from = c 
    val to = c 
    def xform = { t: from.T => t } 
} 

這產生的預測的錯誤:

<console>:12: error: type mismatch; 
found : t.type (with underlying type Identity.this.from.T) 
required: Identity.this.to.T 
     def xform = { t: from.T => t } 

目標基本上是有一個轉換,它轉換容器底層的對象,但能夠說服類型檢查器(沒有可怕的可怕的演員),類型是相同的。

什麼是能夠以這種方式顯示等值和類型關係的最佳方式?

就像我說的,完全開放的改制代碼,我在實際的例子它是一個真正的目的:)

+0

你打算添加_any_類型參數嗎? :) –

回答

4

我想泛型參數可能是形容這種模式更簡單的方法。

可以避開泛型參數都在一起,但是,通過明確地識別出該Container情況下都是類型T

case class Identity(c: Container) extends Transform { 
    val from: Container { type T = c.T } = c 
    val to: Container { type T = c.T } = c 
    def xform = { t: from.T => t } 
} 

或者更簡單:

case class Identity(c: Container) extends Transform { 
    val from: c.type = c 
    val to: c.type = c 
    def xform = { t: from.T => t } 
} 

如果你真行只需要避免ContainerTransform上的通用參數,就可以說服編譯器確定類型的工作方式:

case class Identity[U](c: Container { type T = U }) extends Transform { 
    val from = c 
    val to = c 
    def xform = { t: c.T => t } 
} 

泛型參數U什麼都不做不是給另一名在T型的Container參數等,但也足以做的伎倆!

對我來說,所有這些解決方案都只是強調了類型檢查器在這些類型中看似強大的功能。我無法真正解釋爲什麼他們是必要的或足夠的。根據我的經驗,使用泛型參數更具可預測性(儘管當然它可能更加混亂)。

+0

謝謝!而且你完全正確地認爲類型檢查器可以感受到多大的任意性。我認爲這歸結於在許多情況下等同性是不可判定的。 –

0

由於Container類型不外露,你不能推斷出任何承諾Identity類。想一想,如果你是從另一個圖書館使用它,沒有辦法知道xform是什麼類型,如果你只是給予和Identity對象。真的,你可以使用xform唯一的定義是這樣的:

def xform = { t: from.T => to.data.head } 

你可以調用將與from.data.head的唯一途徑。

另一種方法是放棄路徑依賴的類型和使用更高kinded類型:

trait Container[T] { 
    def data: List[T] 
    } 

    trait Transform[A, B] { 
    val from: Container[A] 
    val to: Container[B] 
    def xform: A => B 
    } 

    case class Identity[A](c: Container[A]) extends Transform[A, A] { 
    val from = c 
    val to = c 
    def xform = { t: A => t } 
    } 
0

如果有人依附於依賴類型,結構細化是一種醜陋但有效的紓困。

abstract class ContainerRefiner { 
    val container: Container 
} 

trait Container { 
    type T 
    def data: List[T] 
} 

trait Transform { 
    val from: Container 
    val to: Container 
    def xform: from.T => to.T 
} 

case class Identity(c: Container) extends Transform { 
    val refiner = new {val container: c.type = c} with ContainerRefiner 
    val from = refiner.container 
    val to = refiner.container 
    def xform = { t: from.T => t } 
} 

任何人都可以請評論這種方法和更高kinded類型之間的優點和缺點嗎?