【问题标题】:Why doesn't Option inherit from Seq and Set?为什么 Option 不继承自 Seq 和 Set?
【发布时间】:2013-11-02 06:30:04
【问题描述】:

我有两个问题,但我希望答案是相互交织的。所以我在玩 flatMapping 不同的参数类型。我得到以下信息:

val s: List[String] = List("f2", "df", "e")     //> s  : List[String] = List(f2, df, e)
val o = s.map(s => if (s.head == 'f')Some(s) else None)
                                              //> o  : List[Option[String]] = List(Some(f2), None, None)
val o1 = s.flatMap(s => if (s.head == 'f')Some(s) else None)
                                              //> o1  : List[String] = List(f2)
val a: Option[String] = Some("Hello")           //> a  : Option[String] = Some(Hello)
val a1 = a.map(s => s.toList)                   //> a1  : Option[List[Char]] = Some(List(H, e, l, l, o))

但是

val a2 = a.flatMap(s => s.toList) //gives
//type mismatch;  found   : List[Char]  required: Option[?]

所以我试图理解 o1 编译而不是 a2 背后的逻辑。然后查看 Option 我想知道为什么 Option 不继承特征:Seq 和 Set? Option 是一个 Seq 因为它保持顺序,它是一个 Set 因为它不包含重复项。通过 Seq 和 Set 它将继承自 Iterable 和 Traversable。

【问题讨论】:

    标签: scala inheritance scala-collections


    【解决方案1】:

    所有GenTraversableOnce 后代的假设是它们包含任意个元素。 API 和假设或依赖于它的机制太多了,例如 BuilderCanBuildFrom

    然而,在更深层次上,重要的是要认识到 for-comprehensions 和 map/flatMapmonadic 操作。 Monad 不可互换——您不能选择一个函数 A => N[B] 并将其传递给 M[A] 以获得 N[B],对于任何 monad M 和 N,以及 Option 和集合是不同的 单子。

    通过许多隐含的魔法,所有集合都被视为单个 monad,这导致人们假设所有 monad应该是可互换的,但事实并非如此。 p>

    然后考虑这样一个简单的案例:

    val x = Option(1)
    val y = List('a', 'b', 'c')
    val z = for {
      a <- x
      b <- y
    } yield (a, b)
    

    z 的类型不能Option,因为结果有多个元素。让它工作的唯一方法是让它变成像Iterable 这样的东西。如果您将Option 视为最多一个元素的集合,这可能对Option 有意义,但对于StateReader monad 之类的东西则没有意义。

    说到将Option 视为最多一个的集合,这是不这样做的另一个原因。 Option 应该被认为是元素的存在或不存在,而不是集合,以及有助于这种微妙区别的可用方法。再说一次,我知道很多人认为这个论点至少是完全虚假的,所以持保留态度。

    【讨论】:

      【解决方案2】:

      虽然可以在 Option 上进行映射,但它既不是序列也不是集合(只有一个元素)。

      选项上的平面图是这样定义的

      flatMap[B](f: (A) ⇒ Option[B]): Option[B]
      

      所以它想要一个返回另一个选项的函数。你的代码

      a.flatMap(s => s.toList)
      

      不返回 Option[_],而是返回一个字符列表(s 是一个字符串,s.toList 返回一个 List[Char])。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-07
      • 2018-03-12
      • 2019-03-03
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 2010-09-18
      • 2021-08-31
      相关资源
      最近更新 更多