假设这个功能
def func[A](data: List[A], mapper: A => String) = {
data.map(item => mapper(item))
}
为什么这段代码无法编译:
val list = List(1, 2, 3)
func(list, a => a.toString)
但是这个确实:
val list = List(1, 2, 3)
func[Int](list, a => a.toString)
或者
val list = List(1, 2, 3)
func(list, (a: Int) => a.toString)
虽然a
类型可以从List
Int
的列表中推断出来。为什么scala不推断这里的类型?
还有其他办法吗?
答案 0 :(得分:11)
还有另一种方式!它也恰好产生了一些很好的合成糖:
def func[A](data: List[A])(mapper: A => String) = data map mapper
看起来像:
func(myList){
case Left(one) => one
case Right(_) => default
}
您无法按照预期的方式获取类型信息的原因是Scala中的类型信息是从左到右。在其他系统中,类型信息是已知的,并在其定义的用途中推导出来。您有时必须解决这些限制,但与此同时,在这种情况下,您可以使用类似于您自己定义的控制结构的东西。
因此...
func[Int]( //I've just told the typer what the information is and it can flow to the right.
func(list //the typer has to deduce the type and without a guide can not figure out what a => a.toString should be
这也是一个旧的“问题”,你可以在这里看到SI-4773。
评论中对Q的回应:
如果您想拥有Seq[A => B]
,那么我会做类似于
func[A, B](data: List[A])(actions: A => B*) = actions map {
data map
}
使用varargs(转换为WrappedArray
,因此map
)接受任何命令列表,以便您可以传递
func(list)(_.name, _.age, _.sex, _.stalker)
就你传递的内容进行抽取和匹配:
func[A, B](data: List[A])(actions: (String, A => B)*) = actions map {
case (name, f) => (name, data map f)
}
其中您使用case
语句来模式匹配并提取元组。