Scala: Constraining the type of a parameter based on the type member of another parameter

前端 未结 2 931
轮回少年
轮回少年 2020-12-18 13:04

I have two traits, each with a type parameter for one of its members. In the first trait, I have a function that takes an instance of the second trait and an instance of the

相关标签:
2条回答
  • 2020-12-18 13:44

    Try:

    def Refuel(car: CarType)(fuel: car.FuelType): Garage = {
    
    0 讨论(0)
  • 2020-12-18 13:47

    Although Daniel's answer works, I would like to point out an alternative, which is kind of my own panacea. I had been struggling a lot with getting path dependent types right, and ended up with the following strategy. It's a bit more 'ugly' as you now need to write an additional type parameter, but this approach has never let me down:

    trait Garage {
      type CarType <: Car[CarType]  // CarType appears as representation type on the right
      def cars: Seq[CarType]
    
      def copy(Cars: Seq[CarType]): Garage
    
      def refuel(car: CarType, fuel: CarType#FuelType): Garage = copy(
        cars.map {  // map is more concise for what you try to achieve
          case `car` => car.refuel(fuel)  // backticks to find the particular car
          case other => other
        })
    }
    
    trait Car[C <: Car[C]] {  // add a 'representation type'
      type FuelType <: Fuel
      def fuel: FuelType
    
      // use 'C' instead of 'Car' everywhere, and qualify the type member with 'C#'
      def copy(fuel: C#FuelType): C
    
      def refuel(fuel: C#FuelType): C = copy(fuel)
    }
    
    trait Fuel
    

    I don't know if this 'representation type' concept has a formal name (I would be interested to know). I tried to look up who taught me this, but didn't find it (at least in stackoverflow).

    0 讨论(0)
提交回复
热议问题