Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala type inference fails in obvious cases #3293

Closed
scabug opened this issue Apr 14, 2010 · 6 comments
Closed

Scala type inference fails in obvious cases #3293

scabug opened this issue Apr 14, 2010 · 6 comments

Comments

@scabug
Copy link

scabug commented Apr 14, 2010

Is there any reason why Scala cannot infer this? It seems that the type of an argument to a polymorphic function is NOT used to fill in types for the type parameters, leading to unnecessary type annotation for other arguments.

scala> def foo[A,B,C](f: A => B, g: B => C): A => C = error("todo")
foo: [A,B,C](f: (A) => B,g: (B) => C)(A) => C

scala> foo((a: Int) => a.toDouble, _ + 2.0)
:6: error: missing parameter type for expanded function ((x$$1) => x$$1.$$plus(2.0))
foo((a: Int) => a.toDouble, _ + 2.0)
^

scala> foo((a: Int) => a.toDouble, b => b + 2.0)
:6: error: missing parameter type
foo((a: Int) => a.toDouble, b => b + 2.0)

Obviously, the compiler knows that the argument f is a function from Int to Double, from which it can infer that the type parameters A and B are Int, and Double, respectively, from which it can infer that g accepts a Double, etc...

This might be better classified as an enhancement, depending on your point of view. :) This bug is probably responsible for like 85% of manual type annotations we have to insert into our code.

This was tested in 2.8.

@scabug
Copy link
Author

scabug commented Apr 14, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3293?orig=1
Reporter: @pchiusano

@scabug
Copy link
Author

scabug commented Apr 14, 2010

@pchiusano said:
Screwed up the formatting, here is the example, properly formatted:

scala> def foo[A,B,C](f: A => B, g: B => C): A => C = error("todo")
foo: [A,B,C](f: (A) => B,g: (B) => C)(A) => C

scala> foo((a: Int) => a.toDouble, _ + 2.0)
<console>:6: error: missing parameter type for expanded function ((x$$1) => x$$1.$$plus(2.0))
       foo((a: Int) => a.toDouble, _ + 2.0)
                                   ^

scala> foo((a: Int) => a.toDouble, b => b + 2.0)
<console>:6: error: missing parameter type
       foo((a: Int) => a.toDouble, b => b + 2.0)
                                   ^

@scabug
Copy link
Author

scabug commented Apr 19, 2010

@dubochet said:
Finding the type of foo requires knowing the types of the parameters (because of static dispatch). This is why knowledge about the type of a method cannot be used, in the general case, to infer the type of its parameters.

In theory, it would be possible to do better inference by creating a complex set of type constraints encompassing simultaneously the knowledge about the parameters and the method. However, this is extremely complex to implement. Because of this complexity, the Scala type inference system will continue to make the above simplification, for the time being.

@scabug
Copy link
Author

scabug commented Apr 19, 2010

@pchiusano said:
Thanks for this response. However, you state: "Finding the type of foo requires knowing the types of the parameters (because of static dispatch)." Isn't that only true if the foo name is overloaded? If there is only one 'foo' method in scope of the correct arity the type of foo can be easily determined. In my experience, it's pretty rare to overload a method and have multiple versions with the same arity and it would be a huge win to improve the type inference in these cases.

If there is something fundamental that I'm missing, please let me know. :)

@scabug
Copy link
Author

scabug commented Apr 19, 2010

@retronym said:
The typical solution is to curry the function, as per Traversable#foldLeft

scala> def foo[A,B,C](f: A => B)(g: B => C): A => C = null
foo: [A,B,C](f: (A) => B)(g: (B) => C)(A) => C

scala> foo((a: Int) => a.toDouble)(_ + 2.0)
res2: (Int) => Double = null

@scabug
Copy link
Author

scabug commented Apr 26, 2010

@dubochet said:
No, there is nothing fundamental you are missing. As I said before, the type inference system has enough information to infer all types (I think), but doesn't do it because the required logic is considered too complex.

If you want to discuss the limitations of the Scala inference mechanism, I would recommend you use the mailing list, where you will get more feedback from a wider audience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant