为什么Option不从Seq和Set继承?

Ric*_*ver 3 inheritance scala scala-collections

我有两个问题,但我希望答案交织在一起.所以我正在玩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))
Run Code Online (Sandbox Code Playgroud)

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

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

Dan*_*ral 7

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

从更深的层面,但是,要认识到的,内涵,而且是重要的map/ flatMap,是一元操作.Monads是不可互换的 - 你不能选择一个函数A => N[B]并将它传递给一个M[A]获得一个N[B],对于任何monad M和N,Option并且集合是不同的 monad.

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

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

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

类型z 不能Option,因为结果有多个元素.它工作的唯一方法就是让它成为一种类似的东西Iterable.Option如果你认为它最多只是一个元素的集合,那么这可能会有所帮助,但对于像a StateReadermonad 这样的东西是没有意义的.

说到Option最多只是一个集合,这是另一个不这样做的原因.一个Option元素应该被认为是一个元素的存在与否,而不是一个集合,以及可用于帮助这种微妙区别的方法.再说一遍,我知道很多人认为这个论点至少是完全虚假的,所以要把它当作一粒盐.