【发布时间】:2010-02-20 21:32:38
【问题描述】:
我正在尝试为在 Scala 中保存列表的列表对象实现我自己的通用展平。 在这一点上,我有
def myFlatten[T](list: List[List[t]]): List[T] = {
for (xs <- list)
for (x <- xs) yield x
}
我收到一条消息:
for xs found Unit required list.
【问题讨论】:
我正在尝试为在 Scala 中保存列表的列表对象实现我自己的通用展平。 在这一点上,我有
def myFlatten[T](list: List[List[t]]): List[T] = {
for (xs <- list)
for (x <- xs) yield x
}
我收到一条消息:
for xs found Unit required list.
【问题讨论】:
def myFlatten[T](list : List[List[T]]) = for(xs <- list; x <- xs) yield x
【讨论】:
非常接近!这是一个有效的方法:
scala> def myFlatten[T](list: List[List[T]]): List[T] = for (xs <- list; x <- xs) yield x
myFlatten: [T](list: List[List[T]])List[T]
或者使用内置的flatten
scala> List(List(1, 2), List(3)).flatten
res0: List[Int] = List(1, 2, 3)
scala> List(Set(1, 2), Set(3)).flatten
res1: List[Int] = List(1, 2, 3)
看看如何在没有for 语法糖的情况下编写这个函数很有启发性。
scala> def myFlatten[T](list: List[List[T]]): List[T] = list flatMap identity
myFlatten: [T](list: List[List[T]])List[T]
scala> myFlatten(List(List(1, 2), List(3)))
res3: List[Int] = List(1, 2, 3)
更新
顺便说一句,List[List[T]] 可以展平为List[T] 的事实是List 是 Monad 的 50%。通常,这称为join。其他 50% 来自您可以将函数 A => B 映射到 List[A] 以产生 List[B] 的事实。它的通用名称是Functor map。 fmap and join on Wikipedia.
为类型构造函数 M 定义 Monad 的另一种方法是使用 pure 操作,它接受 A 类型的值,并返回 M[A];和一个bind 操作,它接受一个M[A],一个函数A => M[B],并产生M[B]。对于列表,pure == List(_) 和 bind = (l: List[A], f: (A => List[B])) => l.flatMap(f)
【讨论】:
就个人而言,我喜欢这种风格:
def myFlatten[T](list: List[List[t]]): List[T] = for {
xs <- list
x <- xs
} yield x
【讨论】: