为什么scala不会从泛型类型参数中推断出类型?

时间:2014-01-15 19:57:52

标签: scala type-inference

假设这个功能

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不推断这里的类型?

还有其他办法吗?

1 个答案:

答案 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语句来模式匹配并提取元组。