Scala 的類型推斷

Scala 的類型推斷

按照官方的說法,Scala 的類型推斷是基于流(flow based)的,假設有方法如下:

foldRight[A, B](xs: List[A], z: B)(f: (A, B) => B): B = {
    case Nil => z
    case h :: t => f(t, foldRight(t, z)(f))
}

這個方法的類型是經過柯里化的、多態(tài)的方法類型,它接收兩組參數列表,一組為普通入參,另一組為函數入參

方法 foldRight[A, B](xs: List[A], z: B])(f: (A, B) => B): B 中的 [A, B] 就是該方法的類型參數。從類型推斷算法執(zhí)行的過程分析,foldRight 需要先用類型參數實例化(所謂類型實例)以后才能被應用到它的入參上,需要先指定 [A, B] 中 A 和 B 的類型

何為類型參數實例化

按照如下調用的方式,可以理解方法的類型參數實例化

// 比如求一個 List[String] 類型列表的長度
val length = foldRight[String, Int](List("a", "b", "c"), 0)((_, Int: len) => 1 + len)

上面的寫法就是先通過 foldRight[String, Int] 指定 foldRight[A, B] 的參數類型為 String 和 Int 來將方法進行類型參數實例化,這樣后面的兩個參數列表就可以應用指定的類型參數進行類型推斷,所以第二個參數列表就可以使用 _ 進行簡寫

普遍調用方式

上述的調用方式,會顯得過于累贅,而且也不能更為精簡的使用泛化函數,普通的調用會是這樣

val sum = foldRight(List(1, 2, 3, 4), 0)(_ + _)

對于這種情況,foldRight 沒有給出確切的類型參數實例,類型推斷算法會改變策略,會先檢查首個參數列表的所有入參類型,并應用到方法的類型參數實例,后續(xù)的參數列表就可以使用方法的類型參數信息了。就是先通過(List(1, 2, 3, 4), 0) 推斷出 foldRight[Int, Int],后續(xù)的 (_ + _) 就可以推斷為 (x: Int, y: Int) => x + y 其中x、y是隨便命名的

具體的過程如下所示:

類型推斷算法總結

當類型推斷算法需要推斷一個多態(tài)方法的類型參數時,他會考慮第一個參數列表的所有入參類型,到此為止。第二個入參列表并不會用來判定方法的類型參數

類庫函數的設計原則

當設計一個接收某些非函數的入參和一個函數入參時,將函數入參單獨放在最后一個參數列表中。這樣,方法的實例類型可以從那些非函數入參推斷出來,而這些類型又能被繼續(xù)用于對函數入參做類型檢查。這樣方法的使用者需要給出的類型信息更少,因而在編寫函數字面量時可以更精簡

其他情況

因為類型算法只會使用第一個參數列表作為方法實例類型的依據,所以在有些局部的情況下,通過顯式添加類型注解來解決問題

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容