简体   繁体   English

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

[英]Why scala doesn't infer type from generic type parameters?

Suppose this function 假设这个功能

def func[A](data: List[A], mapper: A => String) = { 
  data.map(item => mapper(item)) 
}

Why this code doesn't compile: 为什么这段代码不能编译:

val list = List(1, 2, 3)
func(list, a => a.toString)

But this one does: 但是这个做了:

val list = List(1, 2, 3)
func[Int](list, a => a.toString)

Or 要么

val list = List(1, 2, 3)
func(list, (a: Int) => a.toString)

While a type can be inferred from list which is List of Int . 虽然a类型可以从列表中可以推断这是ListInt Why doesn't scala infer the type here? 为什么scala不推断这里的类型?

Is there any other way? 还有其他方法吗?

There is another way! 还有另一种方式! It also happens to make for some nice syntatic sugar: 它也恰好产生了一些很好的合成糖:

def func[A](data: List[A])(mapper: A => String) = data map mapper

which looks like: 看起来像:

func(myList){
  case Left(one) => one
  case Right(_) => default
}

The reason that you can not get the type information to flow the way you'd expect is that type information in Scala is left to right. 您无法按照预期的方式获取类型信息的原因是Scala中的类型信息是从左到右。 In other systems, type information is known and deduced for useage where it is defined. 在其他系统中,类型信息是已知的,并在其定义的用途中推导出来。 You sometimes have to work around these limitations but at the same time, in this case, you can get to work with something that looks akin to your own defined control structure. 您有时必须解决这些限制,但与此同时,在这种情况下,您可以使用类似于您自己定义的控件结构的东西。

So... 所以...

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

This is also an old "issue" you can see here SI-4773 . 这也是一个旧的“问题”,你可以在这里看到SI-4773

Response to Q in Comment : 评论中对Q的回应

If you want to have a Seq[A => B] then I'd do something similar to 如果你想要一个Seq[A => B]那么我会做类似的事情

func[A, B](data: List[A])(actions: A => B*) = actions map { 
  data map
}

which is using varargs (translates to a WrappedArray , hence the map ) to accept any list of commands so that you can pass is 使用varargs(转换为WrappedArray ,因此map )接受任何命令列表,以便您可以通过

func(list)(_.name, _.age, _.sex, _.stalker)

as far as pulling out and matching on what you've passed in: 至于拉出并匹配你传入的内容:

func[A, B](data: List[A])(actions: (String, A => B)*) = actions map { 
  case (name, f) => (name, data map f)
}

wherein you're using the case statement to pattern match and extract the tuple. 其中你使用case语句来模式匹配并提取元组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM