只要你需要自己创建这些类型,它并没有给你太多。但是,只要你让编译器为你做的东西,它会更有用。
我显示此之前,让我们改变表示皮亚诺aritmetic弄成短的一个办法:
sealed abstract class List[+H, N <: Num](val size: N) {
def ::[T >: H](value: T): List[T, Succ[N]] = Cons(value, this)
}
case object Nil extends List[Nothing, Zero.type](Zero)
case class Cons[+H, N <: Num](head: H, tail: List[H, N]) extends List[H, Succ[N]](Succ(tail.size))
type ::[+H, N <: Num] = Cons[H, N]
如果您:
sealed trait Num
case object Zero extends Num
case class Succ[N <: Num](num: N) extends Num
然后,您可以在编译时已知的尺寸创建列表检查用sych list创建的类型,它的尺寸将在其类型中编码:
val list = 1 :: 2 :: 3 :: 4 :: Nil // List[Int, Succ[Succ[Succ[Succ[Zero.type]]]]] = Cons(1,Cons(2,Cons(3,Cons(4,Nil))))
你可以尝试做的下一件事是使用implicits来检查某些东西,例如
trait EvenNum[N <: Num]
implicit val zeroIsEven = new EvenNum[Zero.type] {}
implicit def evenNPlusTwo[N <: Num](implicit evenN: EvenNum[N]) = new EvenNum[Succ[Succ[N]]] {}
有了,你可以强制执行时隐证据可以提供一些操作只能做到:
def operationForEvenSizeList[T, N <: Num](list: List[T, N])(implicit ev: EvenNum[N]) = {
// do something with list of even length
}
operationForEvenSizeList(1 :: 2 :: Nil) // ok
operationForEvenSizeList(1 :: 2 :: 3 :: Nil) // compiler error
至于我可以告诉类型级编程的真正力量在斯卡拉出现时你开始使用implicits来创建新的类型:你可以使用隐式证据,类型类派生和一些结构样板的移除。
一个对泛型编程有很大帮助的库是无形的。我相信,一旦你做了一两次运动练习或者带有暗示的类型派生练习,对你来说这将是一件有趣的事情。
回到你的代码:你可以提供一些暗示,它会为你生成和提供你的类的实例。此外,除了创建新类外,此代码还会执行其他操作,例如组合您将添加到这些类中的元素列表,或者提供从PeanoNumType到Int的转换,或者添加一些在编译时工作的谓词等。天空是极限。