解決類型我有這些模型:在F-界多態性
trait Vehicle[T <: Vehicle[T]] { def update(): T }
class Car extends Vehicle[Car] { def update() = new Car() }
class Bus extends Vehicle[Bus] { def update() = new Bus() }
如果我獲得Vehicle[Car]
的實例,並調用update()
,我會得到一個Car
。由於Car
擴展Vehicle[Car]
(或簡單地說,汽車是一個汽車[汽車]),我可以放心地明確設置結果的類型Vehicle[Car]
:
val car = new Car
val anotherCar = car.update()
val anotherCarAsVehicle: Vehicle[Car] = car.update() // works as expected
但是,如果我想,說,把實例的Car
和Bus
連成一個列表,然後我到列表類型設置爲Vehicle[_ <: Vehicle[_]]
(具有簡單Vehicle[_]
列表和元素調用update()
將產生Any
,但我希望能夠用update()
,所以我不得不使用F-bound類型)。使用存在類型砸了類型的關係,因爲一旦我從車輛獲取潛在汽車/公交車,我再也不能將它轉換爲車輛因爲......好吧,這只是一些存在類型:
val seq = List[Vehicle[_ <: Vehicle[_]]](new Car, new Bus)
val car = seq.head.update()
val carAsVehicle: Vehicle[_ <: Vehicle[_]] = seq.head.update() // fails to compile
所以,Vehicle
用某種類型T
參數化,這是Vehicle[T]
的子類型。當我撕開T
(使用update()
)時,在具體類型的情況下可以 - 例如,如果我剔除了Car
,我可以放心地聲稱我剔除了Vehicle[Car]
,因爲Car <: Vehicle[Car]
。但是如果我剔除存在類型,我無法做任何事情。之前的例子工作,因爲Car
是Vehicle[Car]
,但在這種情況下_
不是Vehicle[_]
。
要指定我的具體問題:對於上面給出的模型(車輛,汽車,公交車),有沒有辦法實現這一點?
def sameType[T, U](a: T, b: U)(implicit evidence: T =:= U) = true
val seq = List[Vehicle[_ <: Vehicle[_]]](new Car, new Bus)
sameType(seq.head.update +: seq.tail, seq) // true
請注意,你可以改變給定的特點,類別和類型的seq
,但有一個限制:update()
必須返回T
,不Vehicle[T]
。
我知道使用無形HList
可以解決這個問題,因爲我不需要使用存在類型(我只是簡單地列出了一輛汽車和一輛公交車,並且該類型的信息將被保留)。但是我想用這個簡單的List
這個特殊的用例。
編輯:
@RomKazanova是,將工作,當然,但我需要之前和之後update()
保留同一類型(這裏所付出的努力的給予好評,雖然;))。
我相信,如果沒有HList或類似的數據結構,這是不可能的,因爲統一的汽車和公共汽車迫使我們使用車型,這種車型會丟失其底層類型是汽車,公交車還是別的東西(我們可以知道的是這是一些類型_ <: Vehicle
)。但我想和你們覈對一下。
我本來以爲'列表[汽車[_ <:汽車[_]]]'是同一類型'名單[汽車[ T] forSome {type T <:Vehicle [T]}]'。作爲一般的經驗法則,我並不介意在任何地方使用'forSome',但我聽說它被Scala 2.13或2.14驅逐。無論如何,非常感謝你,這正是我期待的那種解決方案。 – slouc
我確實從我的REPL記錄中刪除了所有的存在類型警告。所以我認爲這是一種只有通配符才能表達的存在感。我不確定*如果*它會被完全刪除,但如果是的話,我認爲最快的時候會是Dotty變成Scala 3.0或類似的東西。 –
順便說一句,我意外地低估了你:)固定 – slouc