编译时检查一些 属性
Compile time check on some property
给定以下 Scala 代码:
sealed trait Color
case object Red extends Color
case object Blue extends Color
sealed trait Car {
def isBroken: Boolean
def color: Color
}
如何定义这样的方法:
def fixBrokenRedCar(c: A): B
也就是说,A
和B
应该是什么?该方法应该只接受同时为 Red
和 isBroken = true
的 Car。否则它应该发出一个编译错误。此外,输出 B
应包含有关其类型的信息,这样如果我创建另一个方法 destroyRedCar(c: B)
并将其应用于输出,它应该相应地进行编译。
您应该将数据移动到类型级别:
trait Bool
trait T extends Bool
trait F extends Bool
trait Color
trait Red extends Color
trait Blue extends Color
trait Car[Clr <: Color, Brkn <: Bool]
def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = new Car[Red, F]{}
scala> fixBrokenCar(new Car[Blue, T]{})
<console>:16: error: inferred type arguments [Car[Blue,T]] do not conform to method fixBrokenCar's type parameter bounds [Cr <: Car[Red,T]]
fixBrokenCar(new Car[Blue, T]{})
^
<console>:16: error: type mismatch;
found : Car[Blue,T]
required: Cr
fixBrokenCar(new Car[Blue, T]{})
^
scala> fixBrokenCar(new Car[Red, T]{})
res3: Car[Red,F] = $anon@67d9a642
给"destroy"吧:
def destroyRedCar(c: Car[Red, _]) = true
scala> destroyRedCar(fixBrokenCar(new Car[Red, T]{}))
res10: Boolean = true
scala> destroyRedCar(new Car[Red, T]{})
res11: Boolean = true
scala> destroyRedCar(new Car[Blue, T]{})
<console>:15: error: type mismatch;
found : Car[Blue,T]
required: Car[Red, ?]
destroyRedCar(new Car[Blue, T]{})
^
如果您需要 "mutate" Cr
类型(从另一种类型构造一种类型,更准确地说):
trait Car[Clr <: Color, Brkn <: Bool] {
type Copy[C <: Color, B <: Bool] <: Car[C,B] // define "copy" type-method
}
trait BrandedCar[Clr <: Color, Brkn <: Bool] extends Car[Clr, Brkn] {
type Copy[C <: Color, B <: Bool] = BrandedCar[C, B] // implement "copy" type-method
def brand: String = "default"
}
def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = c.asInstanceOf[Cr#Copy[Red, F]]
def checkBrandedCar(c: BrandedCar[_, F]) = true // accepts only branded and fixed
scala> checkBrandedCar(new BrandedCar[Red, F]{})
res10: Boolean = true
scala> checkBrandedCar(new Car[Red, F]{})
<console>:15: error: type mismatch;
found : Car[Red,F]
required: BrandedCar[?, F]
checkBrandedCar(new Car[Red, F]{})
^
scala> checkBrandedCar(fixBrokenCar(new BrandedCar[Red, T]{}))
res12: Boolean = true
您还可以在 Car
的特征中定义一些 def copy[C <: Color, B <: Bool]: Copy[C, B]
方法(例如 类),而不仅仅是 asInstanceOf
.
我假设您可以更改 class 结构。
实现您想要的目标的一种方法是使用类型级编程。这里有一个很好的堆栈溢出 post:Scala type programming resources
下面是一些基于您的原始代码的示例代码,演示了如何使用 Scala 中的类型系统实现这一点。
/*
* Color traits I've left the same except converted the objects
* to classes. This would work just as well with traits. It might
* even be better if the Colors such as Red and Blue are traits
* themselves that extend Color, I'm still just learning this
* method myself.
*/
sealed trait Color
class Red extends Color
class Blue extends Color
/* New trait to represent whether something is broken or not */
sealed trait IsBroken
class Broken extends IsBroken
class NotBroken extends IsBroken
/* Change Car trait to have two type parameters, broken and color */
trait Car[T <: Color, S <: IsBroken]
/* fixBrokenCar signature includes whether a car is broken and it's color */
def fixBrokenRedCar(c: Car[Red, Broken]): Car[Red, NotBroken]
= new Car[Red, NotBroken]{}
val brokenRedCar = new Car[Red, Broken]{}
val fixedRedCar = new Car[Red, NotBroken]{}
val brokenBlueCar = new Car[Blue, Broken]{}
/* Compiles */
fixBrokenRedCar(brokenRedCar)
/* Doesn't compile */
fixBrokenRedCar(fixedRedCar)
/* Doesn't compile */
fixBrokenRedCar(brokenBlueCar)
给定以下 Scala 代码:
sealed trait Color
case object Red extends Color
case object Blue extends Color
sealed trait Car {
def isBroken: Boolean
def color: Color
}
如何定义这样的方法:
def fixBrokenRedCar(c: A): B
也就是说,A
和B
应该是什么?该方法应该只接受同时为 Red
和 isBroken = true
的 Car。否则它应该发出一个编译错误。此外,输出 B
应包含有关其类型的信息,这样如果我创建另一个方法 destroyRedCar(c: B)
并将其应用于输出,它应该相应地进行编译。
您应该将数据移动到类型级别:
trait Bool
trait T extends Bool
trait F extends Bool
trait Color
trait Red extends Color
trait Blue extends Color
trait Car[Clr <: Color, Brkn <: Bool]
def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = new Car[Red, F]{}
scala> fixBrokenCar(new Car[Blue, T]{})
<console>:16: error: inferred type arguments [Car[Blue,T]] do not conform to method fixBrokenCar's type parameter bounds [Cr <: Car[Red,T]]
fixBrokenCar(new Car[Blue, T]{})
^
<console>:16: error: type mismatch;
found : Car[Blue,T]
required: Cr
fixBrokenCar(new Car[Blue, T]{})
^
scala> fixBrokenCar(new Car[Red, T]{})
res3: Car[Red,F] = $anon@67d9a642
给"destroy"吧:
def destroyRedCar(c: Car[Red, _]) = true
scala> destroyRedCar(fixBrokenCar(new Car[Red, T]{}))
res10: Boolean = true
scala> destroyRedCar(new Car[Red, T]{})
res11: Boolean = true
scala> destroyRedCar(new Car[Blue, T]{})
<console>:15: error: type mismatch;
found : Car[Blue,T]
required: Car[Red, ?]
destroyRedCar(new Car[Blue, T]{})
^
如果您需要 "mutate" Cr
类型(从另一种类型构造一种类型,更准确地说):
trait Car[Clr <: Color, Brkn <: Bool] {
type Copy[C <: Color, B <: Bool] <: Car[C,B] // define "copy" type-method
}
trait BrandedCar[Clr <: Color, Brkn <: Bool] extends Car[Clr, Brkn] {
type Copy[C <: Color, B <: Bool] = BrandedCar[C, B] // implement "copy" type-method
def brand: String = "default"
}
def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = c.asInstanceOf[Cr#Copy[Red, F]]
def checkBrandedCar(c: BrandedCar[_, F]) = true // accepts only branded and fixed
scala> checkBrandedCar(new BrandedCar[Red, F]{})
res10: Boolean = true
scala> checkBrandedCar(new Car[Red, F]{})
<console>:15: error: type mismatch;
found : Car[Red,F]
required: BrandedCar[?, F]
checkBrandedCar(new Car[Red, F]{})
^
scala> checkBrandedCar(fixBrokenCar(new BrandedCar[Red, T]{}))
res12: Boolean = true
您还可以在 Car
的特征中定义一些 def copy[C <: Color, B <: Bool]: Copy[C, B]
方法(例如 类),而不仅仅是 asInstanceOf
.
我假设您可以更改 class 结构。
实现您想要的目标的一种方法是使用类型级编程。这里有一个很好的堆栈溢出 post:Scala type programming resources
下面是一些基于您的原始代码的示例代码,演示了如何使用 Scala 中的类型系统实现这一点。
/*
* Color traits I've left the same except converted the objects
* to classes. This would work just as well with traits. It might
* even be better if the Colors such as Red and Blue are traits
* themselves that extend Color, I'm still just learning this
* method myself.
*/
sealed trait Color
class Red extends Color
class Blue extends Color
/* New trait to represent whether something is broken or not */
sealed trait IsBroken
class Broken extends IsBroken
class NotBroken extends IsBroken
/* Change Car trait to have two type parameters, broken and color */
trait Car[T <: Color, S <: IsBroken]
/* fixBrokenCar signature includes whether a car is broken and it's color */
def fixBrokenRedCar(c: Car[Red, Broken]): Car[Red, NotBroken]
= new Car[Red, NotBroken]{}
val brokenRedCar = new Car[Red, Broken]{}
val fixedRedCar = new Car[Red, NotBroken]{}
val brokenBlueCar = new Car[Blue, Broken]{}
/* Compiles */
fixBrokenRedCar(brokenRedCar)
/* Doesn't compile */
fixBrokenRedCar(fixedRedCar)
/* Doesn't compile */
fixBrokenRedCar(brokenBlueCar)