3

Scala 3 幻影类型

 3 years ago
source link: https://blog.oyanglul.us/scala/dotty/phantomtype
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Scala 3 幻影类型

Scala 3 幻影类型

中文 | English


可以跑的源码在这里 👉 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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK