为什么Scala不允许List.map _并在REPL中键入签名
背景
我最近参加了一个初学者Scala聚会,我们正在谈论方法和功能之间的区别(也在深入讨论here). 例如: scala> val one = 1 one: Int = 1 scala> val addOne = (x: Int) => x + 1 addOne: Int => Int = <function1> 这表明val不仅可以具有整数类型,而且可以具有函数类型.我们可以在scala repl中看到类型: scala> :type addOne Int => Int 我们还可以在对象和类中定义方法: scala> object Foo { | def timesTwo(op: Int) = op * 2 | } defined module Foo 虽然方法没有类型(但是具有类型签名),我们可以将其提升为函数以查看它是什么: scala> :type Foo.timesTwo <console>:9: error: missing arguments for method timesTwo in object Foo; follow this method with `_' if you want to treat it as a partially applied function Foo.timesTwo ^ scala> :type Foo.timesTwo _ Int => Int 到现在为止还挺好.我们甚至讨论了函数实际上是如何使用apply方法的对象,以及我们如何使用de-syntactic sugarify表达式来显示: scala> Foo.timesTwo _ apply(4) res0: Int = 8 scala> addOne.apply(3) res1: Int = 4 对我来说,这对学习语言很有帮助,因为我可以内化语法实际意味着什么. 有问题的例子 但是,我们遇到了一种我们无法识别的情况.以一系列字符串为例.我们可以在函数上映射函数,演示基本的Scala集合和函数式编程: scala> List(1,2,3).map(_*4) res2: List[Int] = List(4,8,12) 好的,那么List(1,3).map()的类型是什么?我希望我们也会这样做:在repl中键入技巧: scala> :type List(1,3).map _ <console>:8: error: Cannot construct a collection of type Nothing with elements of type Nothing based on a collection of type List[Int]. List(1,3).map _ ^ 从API定义中,我知道签名是: def map[B](f: (A) ? B): List[B] 但也有一个完整的签名: def map[B,That](f: (A) ? B)(implicit bf: CanBuildFrom[List[A],B,That]): That 题 所以有两件事我不太明白: >为什么正常的函数提升技巧不适用于List.map?有没有办法解除语法糖的错误陈述来证明正在发生的事情? 最后,是否有一种强大的方法来检查REPL的类型和签名? 解决方法
您遇到的问题与Scala,functions are monomorphic,while methods can be polymorphic中的事实有关.因此,必须知道类型参数B和那才能为List.map创建函数值.
编译器尝试推断参数,但不能提出任何合理的参数.如果提供参数,您将获得有效的函数类型: scala> List(1,3).map[Char,List[Char]] _ res0: (Int => Char) => List[Char] = <function1> scala> :type res0 (Int => Char) => List[Char] (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |