我正在学习Scala,并在下面的代码中使用flatMap (摘自filter with flatmap or collect)
我有
list flatMap {
case st: String => Some(st)
case _ => None
}
它可以在List[Any]
上工作并产生List[String]
scala> List(1, "A") flatMap {
| case st: String => Some(st)
| case _ => None
| }
res21: List[String] = List(A)
现在,我对这里的types
感到困惑。如我所想,flatMap
适用于某些monad
,它是对M[M[A]] -> M[A]
的转换。
下面的代码很容易理解,
def flatten(ls: List[Any]): List[Any] = ls flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
由于两种情况都返回一个List[Any]
,它仍然是ls: List[Any]
的同一类型。
但是为什么Some[String]
的{{1}}中的None
和flatMap
是可接受的?
此外,似乎List[Any]
被完全忽略了,而不是被视为一个严重的值?我当时在想可能有一些压缩步骤来消除这些值,例如:
None
有人可以解释这些吗?谢谢!!!
答案 0 :(得分:4)
我认为,flatMap在某些monad上运行,这是从M [M [A]]-> M [A]的转换。
Scala flatMap
比较笼统(有些人不喜欢)。
如果您查看documentation,传递给List#flatMap
的函数就返回GenTraversableOnce[SomeType]
而不是List[SomeType]
就足够了。即使Option
没有扩展GenTraversableOnce
,它们之间也有一个implicit conversion会在此处应用。
此外,似乎完全忽略了None而是将其视为一个严肃的值?
None
对应于一个空集合,Some(x)
对应于一个单元素集合。所以你有
Some(1) ++ Some(2) ++ None ++ Some(3) ==
List(1) ++ List(2) ++ List() ++ List(3) ==
List(1,2,3)
或者,按照您的说法,您没有[1,2,3,,,4]
(没有意义),但是没有[[1],[2],[3],[],[],[4]]
。
答案 1 :(得分:1)
flatMap
不限于相同类型的嵌套集合。传递给flatMap
的函数返回的值可以是任何集合类型。 flatMap
将采用该集合中的每个元素,并将其附加到结果集合中。 Option[T]
的工作方式类似于0或1个元素的集合,因此flatMap
的工作方式与List
,Vector
,Array
或其他集合一样。>
但是,在这种特定情况下,您实际上会使用collect
而不是flatMap
:
list.collect{ case s: String => s }