這裏有幾個類似的問題,我讀了它們,發現沒有答案可以讓我的代碼工作。我想我碰到了一個需要比正常情況下更精確的類型規格的角落案例。如何正確定義一個f綁定多態類型的存在
我的情況用兩個字。我想創建非常簡單的異構列表示例來加深我對scala語言的理解。我給自己設置的限制是:沒有任何形式的暗示,只是普通的scala類型系統。 Implicits可以使許多事情變得更容易,但我想努力嘗試。
我已經工作的代碼,但我想改進它。在這裏它是:
sealed trait HList {
type Self <: HList
def self : Self
def prepend[H](head : H) = HCons[H, Self](head, self)
def ::[H](head : H) = prepend(head)
type Merge[X <: HList] <: HList
def merge[X <: HList](other : X) : Merge[X]
def :::[X <: HList](other : X) = other.merge[Self](self)
}
sealed trait HNil extends HList {
override type Self = HNil
override def self = this
override type Merge[X <: HList] = X
override def merge[X <: HList](other : X) : Merge[X] = other
}
case object HNil extends HNil
final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
override type Self = HCons[H,T]
override def self = this
override type Merge[X <: HList] = HCons[H, T#Merge[X]]
override def merge[X <: HList](other : X) : Merge[X] = HCons(head, tail.merge(other))
}
的Merge
類型構造表示追加兩個列表的類型的結果。需要跟蹤所有嵌套類型。這裏是結果:
val x = "str" :: true :: HNil
val s : String = x.head
val b : Boolean = x.tail.head
val y = 0.5 :: 12 :: HNil
val d : Double = y.head
val i : Int = y.tail.head
val l = x ::: y
val r = y.merge(x)
val sl : String = l.head
val sb : Boolean = l.tail.head
val sd : Double = l.tail.tail.head
val si : Int = l.tail.tail.tail.head
val rd : Double = r.head
val ri : Int = r.tail.head
val rl : String = r.tail.tail.head
val rb : Boolean = r.tail.tail.tail.head
現在我已經做了無聊的介紹。我擔心這一點我已經失去了一半的讀者。我希望我可以將代碼摺疊爲單行。
所以真正的問題是Self
類型和self
方法。他們看起來很醜,我想擺脫他們。我相信f-bound多態可以以自然的方式幫助我。我得到了下面的代碼:
type HAny = X forSome {type X <: HList[X]}
sealed trait HList[Self <: HList[Self]] {this : Self =>
def prepend[H](head : H) = HCons[H, Self](head, this)
def ::[H](head : H) = prepend(head)
type Merge[X <: HList[X]] <: HAny
def merge[X <: HList[X]](other : X) : Merge[X]
def :::[X <: HList[X]](other : X) = other.merge[Self](this)
}
sealed trait HNil extends HList[HNil] {
override type Merge[X <: HList[X]] = X
override def merge[X <: HList[X]](other : X) : Merge[X] = other
}
case object HNil extends HNil
final case class HCons[H, T <: HList[T]](head : H, tail : T) extends HList[HCons[H,T]] {
override type Merge[X <: HList[X]] = HCons[H, T#Merge[X]]
override def merge[X <: HList[X]](other : X) : Merge[X] = HCons[H, T#Merge[X]](head, tail.merge(other))
}
Scala編譯器產生的錯誤,給我很少的見解:
[error] App.scala:23: type arguments [H,T#Merge[X]] do not conform to method apply's type parameter bounds [H,T <: SelApp1.this.HList[T]]
[error] override def merge[X <: HList[X]](other : X) : Merge[X] = HCons[H, T#Merge[X]](head, tail.merge(other))
[error] ^
[error] one error found
轉化爲F-約束多態性順利的前置部分。合併部分產生錯誤。我需要對Merge
類型進行抽象,所以我用HAny
存在類型對它進行了限定,就像我在前面的示例中使用HList
而沒有任何其他類型規範。
但是在後一種情況下,由於編譯器抱怨不恰當的類型,一些類型信息丟失。那麼我如何定義存在類型來存儲構建HCons
所需的所有類型信息呢?也許我需要更復雜的調整來將抽象類型解決方案轉換爲f-bound變體?
費德里科,這是它的工作原理方面有很大的答案,但請你提供有關爲什麼原來的代碼沒有按一些細節不工作,這是嗎?關鍵區別在哪裏?我不認爲我理解這個訣竅的方式是我可以在必要時再次複製它。 – SergGr