Scala flatMap如何消除Nil元素的问题

Scala flatMap如何消除Nil元素的问题,scala,functional-programming,Scala,Functional Programming,我正在阅读《Scala中的函数编程》一书,在数据结构一章的末尾,您被要求按照flatMap实现filter方法。以下是必要的功能和实现: sealed trait List[+A] case object Nil extends List[Nothing] case class Cons[+A](head: A, tail: List[A]) extends List[A] object List { def apply[A](as: A*): List[A] = { if (

我正在阅读《Scala中的函数编程》一书,在数据结构一章的末尾,您被要求按照
flatMap
实现
filter
方法。以下是必要的功能和实现:

sealed trait List[+A]

case object Nil extends List[Nothing]

case class Cons[+A](head: A, tail: List[A]) extends List[A]

object List {
  def apply[A](as: A*): List[A] = {
    if (as.isEmpty) Nil
    else Cons(as.head, apply(as.tail: _*))
  }

  def append[A](l1: List[A], l2: List[A]): List[A] = {
    foldRight(l1, l2)((elem, acc) => Cons(elem, acc))
  }

  def concat[A](ls: List[List[A]]): List[A] = {
    foldLeft(ls, Nil: List[A])(append)
  }

  def map[A, B](l: List[A])(f: A => B): List[B] = {
    foldRight(l, Nil: List[B])((elem, acc) => Cons(f(elem), acc))
  }

  def filter[A](l: List[A])(f: A => Boolean): List[A] = {
    List.flatMap(l)(a => if (f(a)) List(a) else Nil)
  }

  def flatMap[A, B](l: List[A])(f: A => List[B]): List[B] = {
    concat(map(l)(f))
  }

  def foldRight[A, B](l: List[A], z: B)(f: (A, B) => B): B = {
    l match {
      case Nil => z
      case Cons(h, t) => f(h, foldRight(t, z)(f))
    }
  }

  def foldLeft[A, B](l: List[A], z: B)(f: (B, A) => B): B = {
    l match {
      case Nil => z
      case Cons(h, t) => foldLeft(t, f(z, h))(f)
    }
  }
}
实际的函数调用如下所示:

val x = List(1, 2, 3, 4, 5)

List.filter(x)(_ < 3)
val x=List(1,2,3,4,5)
列表过滤器(x)(<3)
据我所知,在映射步骤之后,您将有一个如下所示的列表:
Cons(Cons(1,无),Cons(2,无),Cons(无,无).


我很难看到从最终结果中过滤出
Nil
的元素的位置。

它们不是“过滤掉的”。在列表上应用
concat
后,它们就会消失,因为与空列表串联没有任何作用。

它们不是“过滤掉的”。在列表列表上应用
concat
后,它们就会消失,因为与空列表串联没有任何作用。

Ah,因此它在
foldRight
中使用
Nil
和另一个列表,其中它没有操作,并保留另一个元素。@flybonzai实际实现似乎使用了每一个方法在这个冗长的列表中。但是,是的,在一天结束的时候,
foldRight
中的
case Nil=>z
在连接过程中删除了
Nil
s。啊,所以它在
foldRight
中有一个
Nil
和另一个列表,其中没有操作,并保留了另一个元素。@flybonzai实际的实现似乎不是这样的。@flybonzaio利用这个冗长列表中的每一种方法。但是,是的,最终是
foldRight
中的
case Nil=>z
在串联过程中删除了
Nil
s。