【问题标题】:What's the magic behind this flatMap code?这个 flatMap 代码背后的魔力是什么?
【发布时间】:2018-12-14 17:23:55
【问题描述】:

我正在学习 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]NoneList[Any]flatMap 中是可以接受的?

此外,None 似乎被完全忽略,而不是被视为一个严肃的价值?我在想可能有一些压缩步骤来摆脱这些值,比如:

[1,2,3].concat([,,2,2])
// => (6) [1, 2, 3, empty × 2, 2]
[1,2,3].concat([,,4]).filter(Boolean)
// => (4) [1,2,3,4]

有人能解释一下吗?谢谢!!!

【问题讨论】:

    标签: scala list flatmap


    【解决方案1】:

    正如我所想,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]]

    【讨论】:

      【解决方案2】:

      flatMap 不限于相同类型的嵌套集合。传递给flatMap 的函数返回的值可以是任何集合类型。 flatMap 将获取该集合中的每个元素并将其附加到结果集合中。 Option[T] 的工作方式类似于 0 或 1 个元素的集合,因此 flatMap 的工作方式与 ListVectorArray 或其他集合一样。

      但是在这种特定情况下,您实际上会使用collect 而不是flatMap

      list.collect{ case s: String => s }
      

      【讨论】:

        猜你喜欢
        • 2012-05-15
        • 2012-11-30
        • 2011-04-02
        • 1970-01-01
        • 2010-09-24
        • 1970-01-01
        • 1970-01-01
        • 2018-02-08
        • 2011-02-06
        相关资源
        最近更新 更多