Note that there are some explanatory texts on larger screens.

plurals
  1. POScala: Correcting type inference of representation type over if statement
    text
    copied!<p>This is a follow-up to <a href="https://stackoverflow.com/questions/11274964/">two</a> <a href="https://stackoverflow.com/questions/11236122/">questions</a> on representation types, which are type parameters of a trait designed to represent the type underlying a bounded type member (or something like that). I've had success creating instances of classes, e.g <code>ConcreteGarage</code>, that have instances <code>cars</code> of bounded type members <code>CarType</code>.</p> <pre><code>trait Garage { type CarType &lt;: Car[CarType] def cars: Seq[CarType] def copy(cars: Seq[CarType]): Garage def refuel(car: CarType, fuel: CarType#FuelType): Garage = copy( cars.map { case `car` =&gt; car.refuel(fuel) case other =&gt; other }) } class ConcreteGarage[C &lt;: Car[C]](val cars: Seq[C]) extends Garage { type CarType = C def copy(cars: Seq[C]) = new ConcreteGarage(cars) } trait Car[C &lt;: Car[C]] { type FuelType &lt;: Fuel def fuel: FuelType def copy(fuel: C#FuelType): C def refuel(fuel: C#FuelType): C = copy(fuel) } class Ferrari(val fuel: Benzin) extends Car[Ferrari] { type FuelType = Benzin def copy(fuel: Benzin) = new Ferrari(fuel) } class Mustang(val fuel: Benzin) extends Car[Mustang] { type FuelType = Benzin def copy(fuel: Benzin) = new Mustang(fuel) } trait Fuel case class Benzin() extends Fuel </code></pre> <p>I can easily create instances of <code>Car</code>s like <code>Ferrari</code>s and <code>Mustang</code>s and put them into a <code>ConcreteGarage</code>, as long as it's simple:</p> <pre><code>val newFerrari = new Ferrari(Benzin()) val newMustang = new Mustang(Benzin()) val ferrariGarage = new ConcreteGarage(Seq(newFerrari)) val mustangGarage = new ConcreteGarage(Seq(newMustang)) </code></pre> <p>However, if I merely return one or the other, based on a flag, and try to put the result into a garage, it fails:</p> <pre><code>val likesFord = true val new_car = if (likesFord) newFerrari else newMustang val switchedGarage = new ConcreteGarage(Seq(new_car)) // Fails here </code></pre> <p>The switch alone works fine, it is the call to <code>ConcreteGarage</code> constructor that fails with the rather mystical error:</p> <pre><code>error: inferred type arguments [this.Car[_ &gt;: this.Ferrari with this.Mustang &lt;: this.Car[_ &gt;: this.Ferrari with this.Mustang &lt;: ScalaObject]{def fuel: this.Benzin; type FuelType&lt;: this.Benzin}]{def fuel: this.Benzin; type FuelType&lt;: this.Benzin}] do not conform to class ConcreteGarage's type parameter bounds [C &lt;: this.Car[C]] val switchedGarage = new ConcreteGarage(Seq(new_car)) // Fails here ^ </code></pre> <p>I have tried putting those magic <code>[C &lt;: Car[C]]</code> representation type parameters everywhere, but without success in finding the magic spot.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload