Scala 3 幻影类型
可以跑的源码在这里 👉 https://github.com/jcouyang/meow
Phantom Types 指并不是数据类型必要的类型. 其实在 GADT 的例子中已经见过了.
比如 List[Int]
说明构造 List
只需要知道 Int
.
但如果把类型定义成 List[Int, B]
, 那么 B
就是 phantom type, 因为你在构造 List(1)
其实并不需要 B
类型的值.
但是这个可以随意加的额外的类型格外有用, 比如我们可以用 phantom types 来定义类型安全的 Vector
:
enum Nat {
case Zero
case Succ[A]() extends Nat
}
import Nat._
type Nat2 = Succ[Succ[Zero.type]]
type Nat3 = Succ[Succ[Succ[Zero.type]]]
enum Vector[+N <: Nat, +A] {
case Cons(head: A, tail: Vector[N, A]) extends Vector[Succ[N], A]
case Nil extends Vector[Zero.type, Nothing]
}
import Vector._
val vector2: Vector[Nat2, Int] = Cons(1, Cons(2, Nil))
val vector3: Vector[Nat3, Int] = Cons(1, Cons(2, Cons(3, Nil)))
长度本身是运行时的值,但是通过phantom types我们把长度弄到了类型上, 这样编译器就能帮忙检查比如, head是不是安全:
def typeSafeHead[A](vec: Vector[Succ[Nat], A]):A = vec match
case Cons(head, _) => head
所以如果你想要拿 Nil 的 head, 编译时就会挂:
typeSafeHead(Nil)
Found: (Main.Vector.Nil : Main.Vector[(Main.Nat.Zero : Main.Nat), Nothing]) Required: Main.Vector[Main.Nat.Succ[Main.Nat], Any]
不信? 可以自己在 scastie 上试试: https://scastie.scala-lang.org/jcouyang/JTX3OFXrTCOuq6LNfgRj8Q/8