【问题标题】:Why doesn't Some(List(1,2,3)).flatten compile?为什么 Some(List(1,2,3)).flatten 不编译?
【发布时间】:2014-03-05 17:05:08
【问题描述】:

在 Scala 2.9.1 中,我可以做到

> Some(List(1,2,3)).flatten
List(1,2,3)

但在 Scala 2.10.0 中,

> Some(List(1,2,3)).flatten
Cannot prove that Seq[Int] <:< Option[B]

我发现了this 关闭的错误,但我不明白这个结论,或者它为什么被关闭。

(1) 为什么这在 Scala 2.10 中不起作用(显然是设计使然?)

(2) 我的 2.9 代码的惯用 2.10 等效项是什么?

【问题讨论】:

标签: scala monads scala-2.10


【解决方案1】:

flatten采用外容器的类型。您不能将List 放入Option,因此这是行不通的。相反,首先更改外部容器的类型,以便可以展平:

Some(List(1,2,3)).toList.flatten

【讨论】:

    【解决方案2】:

    flatten 实际上只打算一次处理一个单子。也就是说,它将M[M[T]] 转换为M[T],如List(List(1,2),List(3)).flatten =&gt; List(1,2,3)scala.Predef 提供了将 Option[T] 强制转换为 List[T] 的隐式,但反之则不然。虽然将 Option 视为由零个或一个元素组成的 List 在某种程度上是合理的,但对于具有两个或多个元素的 List,没有通用模式。

    不过,为了方便起见,也支持其他方式:

    List(Some(1),None,Some(2),Some(3)).flatten => List(1, 2, 3)
    

    编辑:我说错了。不是隐式转换为 Option 使这成为可能,而是Option可遍历。在the api docsListflatten其实是:

    def flatten[B](implicit asTraversable: (A) ⇒ GenTraversableOnce[B]): List[B]
    

    【讨论】:

    • Option 不是Traversable。您第一次几乎正确,它已隐式转换为Iterable。如果Option 是可遍历的,那么Option(List(...)).flatten 将被视为Traversable(Traversable(...)).flatten,它会起作用。
    猜你喜欢
    • 1970-01-01
    • 2014-01-09
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 2020-12-04
    • 2020-12-16
    • 2012-10-24
    相关资源
    最近更新 更多