2011-07-31 160 views
12

當我試圖編譯小例子:類型推斷沒有在斯卡拉

trait Foo[A,B] { 
    type F[_,_] 
    def foo(): F[A,B] 
} 

class Bar[A,B] extends Foo[A,B] { 
    type F[D,E] = Bar[D,E] 
    def foo() = this 
} 

object Helper { 
    def callFoo[A,B,FF <: Foo[A,B]](f: FF): FF#F[A,B] = 
    f.foo() 
} 

object Run extends App { 
    val x = new Bar[Int,Double] 
    val y = Helper.callFoo(x) 
    println(y.getClass) 
} 

我得到的錯誤:

[error] src/Issue.scala:20: inferred type arguments 
[Nothing,Nothing,issue.Bar[Int,Double]] do not conform to method callFoo's type 
parameter bounds [A,B,FF <: issue.Foo[A,B]] 
[error]  val y = Helper.callFoo(x) 

顯然,類型推理機制並不能夠推斷出A和B超出酒吧[A,B]。然而,它的工作,如果我通過所有類型的手:

val y = Helper.callFoo[Int,Double,Bar[Int,Double]](x) 

我有辦法避免顯式傳遞類型?

回答

11

你必須的callFoo簽名改成這樣:

def callFoo[A, B, FF[A, B] <: Foo[A, B]](f: FF[A, B]): FF[A, B]#F[A, B] = 

您必須告訴編譯器FF實際上是參數化類型。

+0

@Kipton_Barros:嗯,我選擇讓 - 菲利普答案只是因爲它意味着更少的重構與我目前的代碼庫。 – paradigmatic

+0

@paradigmatic是的,Jean-Philippe的回答非常好。我發現有趣的是,儘管'FF'參數不必更高一些,所以它可以幫助推斷。我嘗試了讓 - 菲利普的技術來解決相關的問題,但是到目前爲止還無法實現它:http://stackoverflow.com/questions/6892781/why-doesnt-scala-fully-infer-type-parameters-when-型參數,是嵌套/ 6893057#6893057 –

2

它會使用類型成員而不是參數?

trait Foo { 
    type A 
    type B 
    type F 
    def foo(): F 
} 

class Bar extends Foo { 
    type F = Bar 
    def foo() = this 
} 

object Helper { 
    def callFoo[FF <: Foo](f: FF): FF#F = 
    f.foo() 
} 

object Run extends App { 
    val x = new Bar{type A=Int; type B=Double} 
    val y = Helper.callFoo(x) 
    println(y.getClass) 
} 

當使用類型成員,是非常有用的知道,他們可以通過細化浮出水面類型參數,如萬里薩賓的回答:Why is this cyclic reference with a type projection illegal?

又見這個最近的問題,這似乎與你相似:Scala fails to infer the right type arguments