flatMap(func)与flatMap(func(_))

TNW*_*TNW 13 scala

由于无法找到该问题的现有问题,我感到非常惊讶.为什么这样,给出:

val p: Int => Option[Int] = Some(_)
List(1, 2, 3).flatMap(p)
Run Code Online (Sandbox Code Playgroud)

我越来越:

<console>:14: error: type mismatch;
 found   : Int => Option[Int]
 required: Int => scala.collection.GenTraversableOnce[?]
       List(1, 2, 3).flatMap(p)
Run Code Online (Sandbox Code Playgroud)

但是如果我用这个替换最后一行,它会按预期编译并工作:

List(1, 2, 3).flatMap(p(_))
Run Code Online (Sandbox Code Playgroud)

我对这个问题的看法是,在p(_)类型推理系统的情况下,决定lambda的类型,以及它找到适当的隐式转换的方式Option[Int](option2Iterable我相信).只是p,类型已知,并且它是不正确的,因此不会尝试转换(并且没有转换Function1返回OptionFunction1返回GenTraversableOnce).

这个推理是对的吗?如果是这样,有什么理由我不应该将此报告为错误/问题?

编辑:一个新的转折:我已经看到p.apply在一些(遗憾的)删除的评论中提到(虽然这是关于编码风格).令人惊讶的是,它的效果一样好p(_).

Ser*_*gey 9

当您键入List(1, 2, 3).flatMap(p(_))幕后所做的事情时,该函数p会被生成并包含在另一个部分应用它的函数中 - 这意味着所有必要的隐式转换(如果有的话)也将应用于此新函数的主体内.

键入时List(1, 2, 3).flatMap(p),不会发生任何函数应用程序,并且您尝试传递Int => Option[Int]与签名不兼容的函数Int => GenTraversableOnce[Int],尽管作用域包含从Option[T]到的隐式转换Iterable[T],但是没有转换Function1[Int, Option[Int]]为已Function1[Int, Iterable[Int]]定义.

其原因可能是因为任意arity的函数由于泛型而具有几乎无限量的变化,并且由于Functions不共享超级,因此对于每种类型的函数都需要相当多的含义.


这是一个扩展flatMap到足以实现所需结果的构造p.然而,它使已经模糊不清的签名flatMap更加清晰(更不清晰).我相信,实现这种行为没有任何技术障碍,但签名的复杂性是scala-collections库经常受到欢迎的原因.

import scala.collection.GenTraversableOnce
import scala.collection.generic.CanBuildFrom

implicit class ListEx[A](list: List[A]) {
  def flatMap2[B, M[_], That](f: A => M[B])
                             (implicit bf: CanBuildFrom[List[A], B, That],
                                       view: M[B] => GenTraversableOnce[B]): That =
    list.flatMap(f andThen view)
}

val p: Int => Option[Int] = Some(_)

List(1, 2, 3) flatMap2 p
Run Code Online (Sandbox Code Playgroud)