在 Scala 中實現泛型函數
我們知道,在 Scala 中方法是可以帶有泛型參數,而函數不行。那麼我們有沒有辦法讓函數模擬出泛型的效果呢?在 Scala 2 中,我們可以通過結構類型實現:
type T = { def apply[A](a: A): A }n
然後可以這樣使用:
val f: T = (identity[Any] _).asInstanceOf[T]n
試試效果:
scala> f(10)nres0: Int = 10nnscala> f("abc")nres1: String = abcn
我們甚至通過這個模擬一個帶有隱式參數的函數:
val f: {def apply[A : ClassTag](args: A*): Array[A]} = Arrayn
然後這樣使用:
scala> f(1, 2, 3)nres0: Array[Int] = Array(1, 2, 3)n
在 Dotty 里,這種做法已經不可行了,但是我們能夠用其他能力來在限定的情況下模擬出類似的效果:
scala> type T = (a: Any) => a.typen// defined alias type T = (a: Any) => a.typenscala> val f: T = identity.asInstanceOf[T]nval f: (a: Any) => a.type = Lambda$1433/1638796611@ef718denscala> f(10)nval res0: Int = 10n
註:res0 的實際類型本來應該是 『10』,不過單例類型在大多數場合都會提升為非單例類型。
不過雖然這樣做能在一定程度上實現泛型方法的效果,但是實際上受限程度還是很大。期待 Dotty 能引入 forall。
推薦閱讀:
※Data class 是好東西,Kotlin 就差一個 pattern matching 了
※#scala#模式匹配
※【太閣x周刊】第十一期:紐約線下活動預告、技術討論群熱點話題、Scala中的Typeclass模式實例、人氣文章
※提議:在Dotty 中使用縮進語法