Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

可扩展数据类型

(Extensible Data Types)

普通的 type 声明定义的代数数据类型,其构造分支在声明时就固定了——后续无法在不修改原定义的情况下添加新的构造子。Koka 还提供了一种可扩展的数据类型:open type。它允许你先声明一个“开放的“类型,然后在程序的任何其他地方(在同一个模块或任何其他模块中)通过 extend type 为它追加新的构造分支。

open type openvar
  A
  B

extend type openvar
  C

fun do-it-try-it(v : openvar) : console ()
  match v
    A -> println("got an A")
    B -> println("got a B")
    C -> println("got a C")
    // 注意:我们可以在代码里匹配 D,尽管它还没被声明
    D -> println("got a D")
    // 兜底
    _ -> println("got something else")

extend type openvar
  D

fun main() : console ()
  do-it-try-it(C)   // 输出: got a C
  do-it-try-it(D)   // 输出: got a D

Tip

由于 openvar 是开放的,理论上任何下游代码都可能继续 extend type openvar 添加新分支。因此,在对 open type 做模式匹配时,编译器无法在编译期保证穷尽性——你可能没有处理未来新增的构造子。所以在实际使用中,通常以通配模式 _​ 收尾,或者只匹配你已知的那些分支。

open type 适用于以下场景:

  • 跨模块的类型演进:基础库定义一个开放类型,各业务模块往里添加自己的构造分支,而不需要修改基础库源码
  • 插件架构:宿主程序定义 open type PluginEvent,各插件通过 extend type PluginEvent 声明自己的事件类型
  • AST / 中间表示的扩展:语言前端定义 open type Expr,各优化 pass 或后端可以扩展新的节点类型