【发布时间】:2019-01-02 17:39:47
【问题描述】:
我正在完成“Scala 中的函数式编程”练习,在第 4 章中有一段关于 Option 类的代码,我认为我很难理解。
我被要求实现 flatMap。我知道 Map 旨在将 A 转换为 B,然后将其包装在 Option 中。那么 flatMap 的目的是什么?如果我没记错的话,在列表中实现的 flatMap 意味着采用将 A 转换为 B 的列表的函数。A => List[B]。原则上,我想这也适用于此。该选项只是一个包含一个元素的列表,我将为其提供一个函数,该函数旨在获取一个 A 并将其包装在一个选项中。
我不知道如何使用 Map 实现 flatMap。明显的实现很简单:
def flatMap(f: A => Option[B]): Option[B] = map(f) getOrElse None
为什么这个实现有效? f 没有A=>B 的类型签名,但它使用这个签名调用 map 就好了。显然,调用 getOrElse(None) 是让它工作的原因,因为如果我把它拿出来,实现就会开始抱怨。但我不明白为什么 scala 解释器不在这里抱怨。我们知道f 返回一个Option[B]。是否返回调用 getOrElse 的选项,然后解包其值以便它可以具有正确的类型签名?如果是这种情况,是否有其他方法可以更清楚地说明它为什么会起作用?
def flatMap[B](f: A => Option[B]): Option[B] =
map((a)=> f(a).getOrElse(None)) // doesn't work
不幸的是,这本书并没有真正提供对 scala 的深入介绍,所以我不确定这是我不理解的语法(很确定它的句法)还是逻辑。
import scala.{Option => _, Some => _, Either => _, _} // hide std library `Option`, `Some` and `Either`, since we are writing our own in this chapter
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case None => None
}
def getOrElse[B>:A](default: => B): B = this match {
case None => default
case Some(b) => b
}
def flatMap[B](f: A => Option[B]): Option[B] =
map(f) getOrElse(None)
def orElse[B>:A](ob: => Option[B]): Option[B] = ???
def filter(f: A => Boolean): Option[A] = ???
}
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
object Option {
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
def variance(xs: Seq[Double]): Option[Double] = ???
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] = ???
def sequence[A](a: List[Option[A]]): Option[List[A]] = ???
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = ???
}
【问题讨论】:
标签: scala types functional-programming