1

考虑在某些案例匹配上编写的 flatMap。例如:

list.flatMap( v =>
    v match {
        case Cond1 => if(something) Some(Int) else None
        //..Other conditions yielding Option[Int]
        case CondN => if(somethingelse) Seq(Int) else Seq()
    })

但是,这不会编译。如果 seq 是 Option[Int] 的全部或 Seq[Int] 的全部,则 flatMap 有效。但如果 Seq 是选项和 Seq 的混合体,则不会。为什么会有这样的限制?这是否解决了我目前无法想到的特殊歧义。

EDIT1 从 REPL 添加代码片段

scala> val a = Seq(Option(1), Seq(2,3))
a: Seq[Equals] = List(Some(1), List(2, 3))

scala> val b = Seq(Seq(1), Seq(2,3))
b: Seq[Seq[Int]] = List(List(1), List(2, 3))

scala> a.flatMap(x=>x)
<console>:9: error: type mismatch;
 found   : Equals
 required: scala.collection.GenTraversableOnce[?]
              a.flatMap(x=>x)
                           ^

scala> b.flatMap(x=>x)
res24: Seq[Int] = List(1, 2, 3)

EDIT2 在菲利波的回答之后,我在 REPL 中尝试了以下代码,它起作用了。

scala> val options = Seq("opt1", "opt2")
options: Seq[String] = List(opt1, opt2)

scala> options.flatMap( x => 
     |      x match {
     |      case "opt1" => Some(1)
     |      case "opt2" => Seq(2,3)
     |      case _ => None
     |      })
res27: Seq[Int] = List(1, 2, 3)

每种情况下的分辨率有何不同。Seq更重要的是,当我映射而不是 flatMap 时,结果与我创建的 a 相同。

scala> options.map( x => 
 |      x match {
 |      case "opt1" => Some(1)
 |      case "opt2" => Seq(2,3)
 |      case _ => None
 |      })
res28: Seq[Equals] = List(Some(1), List(2, 3))  
4

1 回答 1

4

Option是一个GenTraversableOnce但是 scala 在这里需要一些帮助:

  val a: Seq[TraversableOnce[Int]] = Seq(Option(1), Seq(2,3))
  a.flatMap(x=>x)

  res0: Seq[Int] = List(1, 2, 3)

添加问题后进行编辑

我认为,如果您的序列类型是您所期望的,那么一切都归结为传递给 flatMap 的函数。如果 scala 无法确定函数(A) => Traversable[A]的起始序列是Seq[A],我认为我们应该明确一些类型。

现在,回到您的第一个示例,我将其重构为:

list.flatMap {
  case Cond1 if something     => Seq(Int)
  case CondN if somethingelse => Seq(Int)
  case _                      => Seq()
}

毫无疑问,scala 现在能够正确推断类型。

于 2015-12-08T06:01:17.823 回答