This is a follow-up to a previous question where I had a trait Garage with a type member CarType, which itself had a type member FuelType, and I needed a function refuel that could take an instance of CarType as the first argument and an instance of the first argument's FuelType as the second argument.
The answer, the two traits below, was to give Car a representation type C <: Car[C]. The problem that I now have is that I can't figure out how to define the type parameter on the concrete classes implementing Garage, e.g. ConcreteGarage below.
trait Fuel
trait Garage {
type CarType <: 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` => car.refuel(fuel)
case other => other
})
}
trait Car[C <: Car[C]] {
type FuelType <: Fuel
def fuel: FuelType
def copy(fuel: C#FuelType): C
def refuel(fuel: C#FuelType): C = copy(fuel)
}
class ConcreteGarage(val cars: Seq[ConcreteGarage#CarType]) extends Garage {
type CarType = Car[CarType] // Nope
//type CarType = Car[Any] // Nope
//type CarType = Car[Nothing] // Nope
//type CarType = Car[Car] // Nope
//type CarType <: Car[CarType] // Nope
def copy(cars: Seq[CarType]) = new ConcreteGarage(cars)
}