2012-12-14 75 views
4

經過大量的Java和一些Haskell,我想看看Scala。從下面的代碼中,我得到這個錯誤信息斯卡拉列表錯誤

type mismatch; found : List[Nothing] => Option[Nothing] required: List[Int] => Option[Nothing]

我不知道我做錯了什麼:

object MyFirstScalaObject { 

    def main(args: Array[String]) { 
     lazy val testValues:List[List[Int]] = List((1 to 10).toList, null, List()); 

     println( testFunction(last, testValues)); 
    } 

    def testFunction[I, O](f : I => O, inputs : List[I]): 
     List[(I, O)] = 
    inputs.zip(inputs.map(f)); 

    def last[A](xs:List[A]):Option[A] = xs match { 
    case x::Nil => Some(x); 
    case _::xs => last(xs); 
    case _ => None; 
    } 

} 

感謝您的任何意見。

乾杯,

+2

你可以將'testFunction'定義爲'testFunction [I,O](inputs:List [I])(f:I => O)',並將其用作'testFunction(testValues)(last)'。 – senia

+0

senia,我認爲你應該把它變成一個答案,而OP應該讓IMHO接受它。 – Blaisorblade

+0

@Blaisorblade:我已經發布它作爲答案。但它是「如何」,而不是「爲什麼」。 – senia

回答

3

,因爲類型推斷Scala中的工作方式,這是無法確定是什麼類型參數last不得,所以它採取過於保守的後備猜想,這是Nothing

testFunction[List[Int],Option[Int](last, testValues) 

,或者你可以更充分地記錄在testFunction聲明的類型參數之間的關係,這將給型inferencer信息:

,當你調用testFunction您可以顯式指定類型

def testFunction[A, I[_], O[_]](f : I[A] => O[A], inputs : List[I[A]]): List[(I[A], O[A])] 

明確地說,I和O是類型構造函數(kind * - > *),現在f的輸入/輸出類型更具體,推理器可以正確推斷出A的參數t他最後的功能必須是Int。

+0

謝謝燉!我想我明白了。 (編輯)我知道了,但我的scala ide不... – markusw

+0

函數調用類型,也沒有功能定義typecontructing類型。錯誤信息是:知道它需要「List [Int] => Option [Int]」,並假定只有「List [Nothing] => Option [Nothing]」。它可能是textValues-List中包含「null」值的一種壓縮? – markusw

+0

user1905015:空值不是問題;它們不會影響testValues的類型推斷,反正類型推斷也不會發生,因爲無論如何您都指定了完整類型。 燉:類型推斷不及時推斷A. – Blaisorblade

1

一個全面修訂&測試版,採用塞尼亞的想法:

object MyFirstScalaObject { 
    def main(args: Array[String]) { 
     lazy val testValues = List((1 to 10).toList, null, List()) 
     println(testFunction(testValues)(last)) 
    } 

    def testFunction[I, O](inputs: List[I])(f: I => O): List[(I, O)] = 
    inputs.zip(inputs.map(f)) 

    def last[A](xs: List[A]): Option[A] = xs match { 
    case x :: Nil => Some(x) 
    case _ :: xs => last(xs) 
    case _ => None 
    } 
} 

類型推斷進行左到右;來自一個參數列表的信息在下一個參數列表中使用。 在此代碼,當調用testFunction Scala中可從第一參數推斷I,那麼它可以喂I作爲函數f找出它的類型的輸入類型(即,該參數last施加A = Int),那麼它最終從函數的返回類型獲得O的值。

1

我不能告訴你爲什麼在scala中的類型推斷這樣工作。

但有common way來幫助編譯器在這種情況下 - parameter sections

def testFunction[I, O](inputs : List[I])(f: I => O): List[(I, O)] = inputs.zip(inputs.map(f)) 

用法:

testFunction(testValues)(last) 

類似的解決方案是添加方法testFunctionList類:

class LastsHelper[T](inputs: List[T]) { 
    def testFunction[O](f: T => O): List[(T, O)] = inputs.zip(inputs.map(f)) 
} 
implicit def toLastsHelper[T](inputs: List[T]) = new LastsHelper(inputs) 

您可以使用這些方法像List方法:

testValues.testFunction(last)