哦哇,这是一个旧的!我会清理一下代码,并将其与当前惯用的约定揪成一行开始:
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
相当正确,现在更新:) –