Aladdin - Scala Bugtracking
[#1246] project: compiler priority: medium category: bug
submitter assigned to status date submitted
Adriaan Gilles fixed 2007-07-27 09:31:31.0
subject unexpected error using structural types: Parameter is defined as type variable T in a refinement.
code
// based on code by Jon Pretty
object Test {
   type Summable[T] = { def +(v : T) : T }

// we can now directly use a type bound, as e.g., Int should be a structural subtype of Summable[Int]
   def sum[T <: Summable[T]](xs : List[T]) = xs.reduceLeft[T](_ + _)
}
what happened
error: Parameter is defined as type variable T in a refinement.
  def sum[T <: Summable[T]](xs : List[T]) = xs.reduceLeft[T](_ + _)
                                                               ^

Note: inlining Summable[T] gave rise to a cyclic reference error (should I file a separate report on that?)
   def sum[T <: { def +(v : T) : T } ](xs : List[T]) = xs.reduceLeft[T](_ + _)
what expected no error
[back to overview]
Changes of this bug report
Martin  edited on  2007-07-27 10:13:02.0
I don't understand the error message?
Martin  edited on  2007-07-27 11:20:26.0
Concerning the cyclic reference error: This has nothing to do with structural types, but happens for every F-bounded type refinement. To see that, just make Summable into a class instead of a type alias. I have become more and more convinced that F-bounds are a pain in the neck (they also seriously mess up type inference and make subtype checking incomplete). Maybe we can eliminate them? I see only one way to do this: Replace F-bounds by higher-kinded types. Here's a sketch: We now have:
  def less[T <: Ordered[T]](x: T, y: T) = x < y
Instead of that we could maybe write:
  def less[O[X = T] <: Ordered[X], T]
           (x: O[T], y: O[T]) = 
           x < y
One thing that's tricky is that we should be able to complete the example as follows:
  class Str extends Ordered[Str]
  less[Str, Str](x, y)
That is the first parameter Str would need to match the signature
  O[X] <: Ordered[X]
It doesn't of course, because it is not polymorphic. However, we have specified in the signature of `less' that the
  O[X] <: Ordered[X] 
relationship needs to hold only for X = T, and T is Str, so the types work out. This is all very preliminary. It's driven by the motivation that using refinements instead of higher-kinded types we can eliminate the F-bound:
  trait Ordered { 
    type Elem; 
    def < (x: Elem, y; Elem): Boolean 
  }
  def less[T, O <: Ordered{ type Elem = T }]
           (x: Ordered { type Elem = T }, 
            y: Ordered { type Elem = T }) = 
           x < y
  less[Str, Str](x, y)
Is this better than F-bounds? I am not sure yet. But it seems worth investigating. Another requirement for this is that we can do type inference for such higher-kinded types. Adriaan, do maybe you want to try you hand with this?
Gilles  edited on  2007-07-27 13:18:28.0