4
如果我的名字有關斯卡拉的最討厭的事情,這將是爲下面的代碼:泛型類型和類型參數的Scala類型推斷 - 爲什麼它不起作用?
trait G[+T]
class H[+T] extends G[T]
def f[A<:G[X], X<:Int](g :A)
val g :H[Int]
f(g)
編譯器推斷類型F中的最後一次通話[H [INT],沒什麼]和在我面前抱怨自己的愚蠢。
但是知道scala,它實際上比我知道得更清楚。它背後的原因是什麼?由於G和H對於T來說是協變的,所以對於任何類型S來說都是S <: G[X] with H[_] <=> S<: H[X]
。這一缺點使我設計了一切,避免明確地指定類型 - 它可能看起來像什麼都沒有,但是當名稱變成'真實'長度和幾乎任何方法都是泛型的,並且通常在兩個泛型類型上工作,事實證明,大多數代碼都是類型聲明。
編輯: 上面的情況是由諾亞解決的,但是當派生類與基類不同,如下所示?
trait G[+X]
class H[+X, Y] extends G[X]
class F extends G[Int]
def f[A<:G[X], X<:Int](g :A) = g
val h: H[Int, String] = ???
val g :F = ???
f(g)
f(h)
謝謝,它有一定的幫助,看起來像在這裏circumvenes問題。但是,如果H是另一種類型,它將無濟於事 - 需要更多的類型參數或沒有,從而實例化G的參數。或者如果H在其參數上引入界限。所以我仍然對如果上述不起作用的理由感興趣。 – Turin
你必須給出另一個不起作用的例子,我敢肯定,你通常可以讓編譯器同意你的看法。上面發生的事情是,編譯器無法從'g:A'中提取類型。它可以發現'A'是'H [Int]',但即使你說'A <:G [X]',你也沒有指定'X',所以它會成爲barf。在我給出的例子中,指定了類型'X',以便編譯器可以推斷它。 – Noah
增加了解釋更實際案例的代碼。 – Turin