Scala - Flatmap一系列选项和Traversable

时间:2015-12-08 05:41:04

标签: scala flatmap

考虑在一些案例匹配上编写的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是Options和Seqs的混合。为什么会有这样的限制?这是否解决了我现在无法想到的特定模糊性。

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 在Filippo的回答之后,我在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)

每种情况下的分辨率有何不同。 更重要的是,当我映射而不是flatMap时,结果与我创建的Seq 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))  

1 个答案:

答案 0 :(得分:4)

OptionGenTraversableOnce,但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现在能够正确地推断出类型。