Scala:基于另一个参数的类型成员约束参数的类型 [英] Scala: Constraining the type of a parameter based on the type member of another parameter
问题描述
我有两个特征,每个特征都有其成员之一的类型参数.在第一个特征中,我有一个函数接受第二个特征的实例和第二个特征的类型成员的实例.此函数调用第二个特征中的函数,该函数期望其类型成员的该实例.但是,我无法弄清楚如何正确地参数化调用以使其真正起作用.这是一个失败的简化示例:
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 second trait's type member. This function calls a function in the second trait that is expecting that instance of its type member. However, I cannot figure out how to properly parameterize the call so that this actually works. Here is a simplified example that fails:
trait Garage {
type CarType <: Car
def Cars: Seq[CarType]
def copy(Cars: Seq[CarType]): Garage
def Refuel(car: CarType, fuel: CarType#FuelType): Garage = {
val car_index = Cars.zipWithIndex.find(_._1 == car).get._2
copy(Cars.updated(car_index, car.Refuel(fuel)))
}
}
trait Car {
type FuelType <: Fuel
def Fuel: FuelType
def copy(Fuel: FuelType): Car
def Refuel(fuel: FuelType): Car = {
copy(fuel)
}
}
trait Fuel
失败并出现以下错误:
error: type mismatch;
found : fuel.type (with underlying type Garage.this.CarType#FuelType)
required: car.FuelType
copy(Cars.updated(car_index, car.Refuel(fuel)))
^
我如何约束 Garage.Refuel
函数,使其接受 Car
和任何该类型的 Fuel
可接受的 Fuel
代码>汽车代码>?
How do I constrain the Garage.Refuel
function so that it accepts a Car
and any Fuel
that is acceptable to that type of Car
?
推荐答案
尽管 Daniel 的回答有效,但我想指出一个替代方案,这是我自己的灵丹妙药.我一直在努力使路径依赖类型正确,并最终采用以下策略.这有点难看",因为您现在需要编写额外的类型参数,但这种方法从未让我失望:
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
我不知道这个表示类型"概念是否有正式名称(我很想知道).我试图查找是谁教我的,但没有找到(至少在 stackoverflow 中).
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).
这篇关于Scala:基于另一个参数的类型成员约束参数的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!