哦哇,這是一箇舊的!我會清理一下代碼,並將其與當前慣用的約定揪成一行開始:
case class Flat[T, U](fn: T => List[U])
implicit def recFlattenFn[T, U](
implicit f: Flat[T, U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)
def recFlatten[T, U](xs: List[T3])(implicit f: Flat[List[T], U]) = f fn xs
然後,事不宜遲,打破代碼。首先,我們有我們的Flat
類:
case class Flat[T, U](fn: T => List[U])
這只不過是該函數T => List[U]
一個名爲包裝器,給出T
類型的實例時,將建立一個List[U]
的功能。請注意,這裏的T
也可以是List[U]
或U
或List[List[List[U]]]
等。通常,這樣的函數可以直接指定爲參數的類型。但是我們將會使用這個暗含的,所以命名的包裝避免了任何隱含衝突的風險。
然後,從recFlatten
向後工作:
def recFlatten[T, U](xs: List[T])(implicit f: Flat[List[T], U]) = f fn xs
這種方法將採取xs
(一List[T]
),並將其轉換爲U
。要做到這一點,它定位的Flat[T,U]
一個隱含的實例,並調用封閉功能,fn
然後,真正的魔力:
implicit def recFlattenFn[T, U](
implicit f: Flat[T, U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)
這滿足由recFlatten
所需的隱含參數,它也需要另一個隱含paramater 。最關鍵的是:
recFlattenFn
可以作爲自己的隱含參數行事
- 它返回一個扁平[列表[X],X],所以
recFlattenFn
只會被隱式解析爲Flat[T,U]
如果T
是List
- 若隱解析失敗的隱含
f
可以回退到默認值(即T
不是一個List
)
Perha PS,這是最好的在實施例之一的上下文中理解:
recFlatten(List(List(1, 2, 3), List(4, 5)))
- 類型
T
被推斷爲List[List[Int]]
- 隱查找嘗試用於`平[列表[列表[INT]] C]
- 這是通過一個匹配遞歸定義
recFlattenFn
廣義地說:
recFlattenFn[List[List[Int]], U] (f =
recFlattenFn[List[Int], U] (f =
Flat[Int,U]((xs: T) => List(xs)) //default value
)
)
注意PARAMS [Int,_]
失敗,這場比賽,因爲Int
不是List
recFlattenFn
將只匹配了Flat[List[X], X]
和隱式的搜索類型。這是觸發回退到默認值的原因。
類型推斷也倒過來了該結構,在遞歸的每個層次解決U
PARAM:
recFlattenFn[List[List[Int]], Int] (f =
recFlattenFn[List[Int], Int] (f =
Flat[Int,Int]((xs: T) => List(xs)) //default value
)
)
這僅僅是一個Flat
實例的嵌套,每一個(除了最裏面的)執行flatMap
操作來展開嵌套List
結構的一個級別。最裏面的Flat
只是封裝所有的單個元素在一個單一的List
備份。
證明完畢
謝謝你,有很大幫助。我想在你的例子中,類型參數是通過包裝關閉的。這將編譯'recFlatten [列表[INT],INT](列表(列表(1,2,3),列表(4,5)))( recFlattenFn [列表[INT],INT](F = recFlattenFn [詮釋,Int](f = )[Int,Int]((xs:Int)=> List(xs))//默認值 ) ) ) ' – huynhjl
相當正確,現在更新:) –