首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >flatMap(func)与flatMap(func(_))

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

Stack Overflow用户
提问于 2016-06-09 12:25:24
回答 2查看 328关注 0票数 13

我很惊讶没能找到这个问题的答案。为什么呢,因为:

代码语言:javascript
复制
val p: Int => Option[Int] = Some(_)
List(1, 2, 3).flatMap(p)

我得到了:

代码语言:javascript
复制
<console>:14: error: type mismatch;
 found   : Int => Option[Int]
 required: Int => scala.collection.GenTraversableOnce[?]
       List(1, 2, 3).flatMap(p)

但是,如果我用这一行替换最后一行,它就会像预期的那样编译和工作:

代码语言:javascript
复制
List(1, 2, 3).flatMap(p(_))

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

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

编辑:一个新的转折:我在一些(遗憾的)被删除的评论中提到了p.apply (尽管这是关于编码风格的)。令人惊讶的是,它的工作效果与p(_)一样好。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-09 13:02:52

当您输入List(1, 2, 3).flatMap(p(_))时,在幕后所做的就是在另一个部分应用它的函数中生成和包装p --这意味着所有必要的隐式转换(如果有的话)也将在这个新函数的主体中应用。

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

这可能是因为任意的函数由于泛型而几乎有无穷大的变化,而且由于Functions不共享一个超特性,这就需要对每种类型的函数都进行大量的关联。

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

代码语言:javascript
复制
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
票数 9
EN

Stack Overflow用户

发布于 2016-06-09 13:11:53

代码语言:javascript
复制
List(1, 2, 3).flatMap(p(_))

汇编如下:

代码语言:javascript
复制
List(1,2,3).flatMap(x => p(x))

p(x)返回时,Option[Int]flatMap需要GenTraversableOnce[Int],所以应用了scala.Option.option2Iterable

选项不继承GenTraversableOnce。要使此语法工作:

代码语言:javascript
复制
List(1,2,3).flatMap(p)

您需要从Int => Option[Int]Int => GenTraversableOnce[Int]的隐式转换,如下所示:

代码语言:javascript
复制
import scala.collection.GenTraversableOnce

implicit def conv(c: Int => Option[Int]): Int => GenTraversableOnce[Int] = {
    a => Option.option2Iterable(c(a))
}
val p: Int => Option[Int] = Some(_)
List(1, 2, 3).flatMap(p)

对我来说,这不是一个bug,但我同意,这也不是直观的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37725975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档