Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help figuring out scala compiler errors

I have been working on a project in scala, but I am getting some error messages that I don't quite understand. The classes that I am working with are relatively simple. For example:

abstract class Shape
case class Point(x: Int, y: Int) extends Shape
case class Polygon(points: Point*) extends Shape

Now suppose that I create a Polygon:

val poly = new Polygon(new Point(2,5), new Point(7,0), new Point(3,1))

Then if I attempt to determine the location and size of the smallest possible rectangle that could contain the polygon, I get various errors that I don't quite understand.

Below are snippets of different attempts and the corresponding error messages that they produce.

val upperLeftX = poly.points.reduceLeft(Math.min(_.x, _.x))

Gives the error:
"missing parameter type for expanded function ((x$1) => x$1.x)"

val upperLeftX =  
         poly.points.reduceLeft((a: Point, b: Point) => (Math.min(a.x, b.x)))

Gives this error:
"type mismatch;
found : (Point, Point) => Int
required: (Any, Point) => Any
"

I am very confused about both of these error messages. If anyone could explain more clearly what I am doing incorrectly, I would really appreciate it. Yes, I see that the second error says that I need type "Any" but I don't understand exactly how to implement a change that would work as I need it. Obviously simply changing "a: Point" to "a: Any" is not a viable solution, so what am I missing?

like image 223
klactose Avatar asked May 20 '10 05:05

klactose


2 Answers

The type of reduceLeft is reduceLeft[B >: A](op: (B, A) => B): B, A is Point, and you are trying to apply it to (a: Point, b: Point) => (Math.min(a.x, b.x)).

The compiler reasons thus: Math.min(a.x, b.x) returns Int, so Int must be a subtype of B. And B must also be a supertype of Point. Why? B is the type of the accumulator, and its initial value is the first Point in your Polygon. That's the meaning of B >: A.

The only supertype of Int and Point is Any; so B is Any and the type of op should be (Any, Point) => Any, just as the error message says.

like image 161
Alexey Romanov Avatar answered Sep 20 '22 03:09

Alexey Romanov


This is Scala 2.8.0.RC2

scala> abstract class Shape
defined class Shape

scala> case class Point(x: Int, y: Int) extends Shape
defined class Point

scala> case class Polygon(points: Point*) extends Shape
defined class Polygon

scala> val poly = new Polygon(new Point(2,5), new Point(7,0), new Point(3,1))
poly: Polygon = Polygon(WrappedArray(Point(2,5), Point(7,0), Point(3,1)))

scala> val upperLeftX = poly.points.reduceLeft((a:Point,b:Point) => if (a.x < b.x) a else b)
upperLeftX: Point = Point(2,5)

reduceLeft requires here a function of the type (Point, Point) => Point. (more precisely (B, Point) => B with B with a lower bound to Point. See Scaladoc at the method reduceLeft.

like image 45
michael.kebe Avatar answered Sep 21 '22 03:09

michael.kebe