1

免责声明:这是家庭作业的一部分。我想为自定义 List 对象实现 flatMap。我已经成功实现了地图,但是我对 flatMap 有问题。我不知道如何展平从地图中获得的列表列表。我不知道我是否真的应该使用地图。

trait List[+A] {
  /** The first element */
  def head: A
  /** The rest of the elements */
  def tail: List[A]
  def flatMap[B](f: A => List[B]): List[B]
  def map[B](f: A => B): List[B]

  // Concatenate two lists
  def concat[B >: A](that: List[B]): List[B] = this match {
    case Empty => that
    case NonEmpty(head, tail) => NonEmpty(head, tail concat that)
  }
}

case object Empty extends List[Nothing] {
  def head = throw new UnsupportedOperationException("Empty.head")
  def tail = throw new UnsupportedOperationException("Empty.tail")
  def flatMap[B](f: Nothing => List[B]): List[B] = Empty
  def map[B](f: Nothing => B): List[B] = Empty

  override def toString = "Empty"
}

case class NonEmpty[A](head: A, tail: List[A]) extends List[A] {

  def map[B](f: A => B): List[B] = {

    NonEmpty(f(head), tail.map(f))

  }
def flatMap[B](f: A => List[B]): List[B] = {
    val a = this.map(f)
    for (x <- a; y <- x) yield y
  }
}
4

2 回答 2

3

由于这是一个家庭作业,我不想给你一个完整的解决方案,只是一些提示。

  1. 您不需要map实现flatMap(实际上相反更容易实现)
  2. 你有你需要的一切(flatMap接受一个返回 aList[B]Listconcat定义的函数)
  3. 实施第flatMap一个Empty;-)
于 2012-12-29T14:33:50.333 回答
2

您必须为长度为 n 的列表编写 flatMap。假设您已经解决了一个长度为 n-1 的列表,请尝试解决它。如果你能做到这一点,那么你就解决了这个问题,因为 n => n-1 => ... => 1 => 0,而对于 0,你已经有了解决方案。

这种思维适合你的List,因为它是递归类型。

你已经用 map 做了这件事,用 flatMap 做同样的事情。这两个函数都是从List[A]到List[B]的转换,唯一的区别是他们可以使用的工具,map有一个将A转换为B的函数,而flatMap有一个将A转换为List[B]的函数

于 2012-12-29T15:23:01.167 回答