跳到主要内容

weekly 2024-07-08

· 阅读需 4 分钟

MoonBit 更新

  • 【重大更新】修改 array slice 的语法,从 arr[start..end] 修改为类似 Python 的 arr[start:end]。这是为了避免和接下来要支持的 cascade method call x..f() 产生语法冲突。旧的语法会在近期删除。

  • 【Wasm后端重大更新】将 fn init 中的代码编译到 start section。 之前版本中的 fn initfn main 代码块中的代码都会被编译到一个特殊函数中,这个特殊函数会被导出为 "_start" 函数,因此宿主环境需要调用 "_start" 函数来进行初始化和执行 main 函数 新版本中会使用 wasm 标准中的 start section 来存放 fn init 中的代码,从而在加载 wasm 模块的过程中完成初始化,这意味着 fn init 中代码的执行不再需要调用 "_start" 函数,只有需要执行 main 函数的时候才需要调用 "_start".

  • 【重大更新】test block 不再返回 Result 类型的结果。 现在的 test block 中使用错误处理机制对测试失败的情况进行处理,鼓励使用标准库中的 inspect 函数,和 @test 包中的 @test.eq 等辅助函数编写测试,比如:

test "unwrap should return value on Some" {
let some : Int? = Some(42)
inspect(some, content="Some(42)")!
@test.eq(some.unwrap(), 42)!
}
  • 支持使用 @pkg.C 来跨包使用构造器,比如如果在 @pkgA 中包含如下声明:
// pkgA
pub enum E1 { C1 } derive(Debug)

enum E1_hidden { C1 }

现在可以在另一个包中对 E1 的构造器 C1 直接进行使用,比如:

// pkgB
fn main {
debug(@pkgA.C1)
}

当在同一个包中,如果出现重复的 public constructor,则会报错,比如:

pub enum E1 {
C1
}

pub enum E2 {
C1
^^ ------ There can be at most one public constructor with name C1.
}

标准库更新

  • 迁移到新的错误处理机制。

  • 迁移到无符号整数,移除了Int和Int64类型旧的compare_udiv_umod_u函数;调整了下面的API:

    • Int32.trunc_double_uInt64.trunc_double_u 更改为 UInt.trunc_doubleUInt64.trunc_double

    • Int64::extend_i32_u 更改为 UInt64::extend_uint

    • Double::convert_i32_uDouble::convert_i64_u 更改为Double::convert_uintDouble::convert_uint64

构建系统更新

  • moon version --all 现在会显示 moonrun 的版本信息。
$ moon version --all
moon 0.1.20240705 (0e8c10e 2024-07-05) ~/.moon/bin/moon
moonc v0.1.20240705+7fdd4a042 ~/.moon/bin/moonc
moonrun 0.1.20240703 (52ecf2a 2024-07-03) ~/.moon/bin/moonrun
  • 修改moon new创建项目的license字段默认为空。

  • 默认开启诊断信息渲染 render

工具链更新

  • VSCode 插件安装MoonBit工具链功能调整。工具链安装的默认版本由总是安装最新版本调整为安装对应插件版本的工具链。

weekly 2024-07-01

· 阅读需 3 分钟

MoonBit 更新

  • 在没有歧义的情况下,enum构造器的使用可以省略类型前缀。比如现在可以直接使用 Some(42) 而不需要写 Option::Some(42);如果当前环境中有两个类型 T1T2 都定义了某个构造器 C,那么在使用的时候则需要通过上下文中的类型或者类型前缀指明是 T1::C 还是 T2::C,否则编译器会报错

  • 添加 UInt64 内建类型,支持加、减、乘、除、模以及 UInt64/Int64 的互相转换。

fn main {
let a = 0UL
let b : UInt64 = 1UL
println(a - b) //18446744073709551615
}
  • !! 后缀的语义修改为捕获函数调用中可能出现的错误,并返回 Result 类型,比如
fn f() -> Int!String { .. }
fn main {
let res = f()!! // res: Result[Int, String]
println(res)
}
  • moon test 中支持使用错误类型表示测试失败的情况,比如
fn eq[T : Debug + Eq](a : T, b : T, ~loc : SourceLoc = _) -> Unit!String {
if a != b {
let a = debug_string(a)
let b = debug_string(b)
raise ("FAILED: \(loc) `\(a) == \(b)`")
}
}

test "test_eq" {
eq(1+2, 3)!
}
  • 标准库中的 I/O 相关操作只保留了 println,其他操作将会在 io package 中提供

标准库更新

  • 统一 T::new()/T::make() 等创建容器对象的函数风格,移除了 T::with_capacity

  • 原先的 iteriteri 重命名为 eacheachiiter_reviter_revi 重命名为 each_reveachi_rev

  • as_iter 重命名为iter

构建系统更新

  • 预计将于本周开源

工具链更新

  • 优化调试体验,现在⽤户可在 JavaScript Debug Terminal 中执⾏ moon run --target js --debug 进行调试

  • moon info 和覆盖率工具适配错误类型和错误处理

weekly 2024-06-24

· 阅读需 2 分钟

MoonBit 更新

  • 支持了 32 位无符号整数
let num = 100U // 32位无符号整数的字面量需要后缀U
  • 在 wasm 后端导出返回值类型为 Unit 的函数时,之前导出函数的类型中会有 (result i32),现在 MoonBit 编译器会自动生成一个没有返回值 wrapper 函数,并将其进行导出

  • moonbitlang/core 的 API 一致性调整

    • forall/existall/any统一为all/any
    • containsmember 统一为contains

IDE 更新

  • 修复了 rename method 时候会丢失 type prefix 的 bug

  • 增加了 try ... catch ... 表达式中的 match clause 中补全的功能

构建系统更新

  • 增加了诊断信息渲染功能,目前还在试验阶段。可通过设置环境变量 MOON_RENDR=1 启用

diagnosis.png

  • moon bench 命令改为 moon generate-build-matrix,bench 子命令留待后续使用

weekly 2024-06-17

· 阅读需 3 分钟

MoonBit 更新

  • 支持了错误处理机制
  1. 函数返回值类型可以用 Int!String 来标识这个函数正常情况下返回 Int ,错误情况下会抛出类型为 String 的错误值,比如
fn div(x: Int, y: Int) -> Int!String { .. }
  1. raise 关键字用于中断当前控制流,直接抛出错误,比如
fn div(x: Int, y: Int) -> Int!String {
if y == 0 { raise "divide by 0" }
x / y
}
  1. try { expr0 } catch { pattern1 => expr1; pattern2 => expr2; .. } 表达式可以用于捕获 expr0 中抛出的错误,并对其进行模式匹配来处理,比如下面这个函数调用上面的 div 函数,并在 div 函数抛出错误的时候将错误信息打印,并返回默认值
fn div_with_default(x: Int, y: Int, default: Int) -> Int {
try {
div(x, y)!
} catch {
s => { println(s); default }
}
}
  1. 此外,可以用后缀运算符 !!! 进行错误处理,这些后缀运算符只能应用于函数调用,其中: f(x)! 将调用 f 的过程中发生的错误立即重新抛出。 f(x)!! 则会在 f 发生错误的情况下直接 panic,其等价于
try { f(x)! } catch { _ => panic() }

函数调用的形式包括方法调用,中缀运算符和管道运算符的调用,比如

fn init {
let _ = x.f()!!
let _ = (x + y)!!
let _ = (x |> f)!!
}
  1. 最后,对可能会抛出错误的函数如果没有使用上述任何错误处理,那么则会报 unhandled error 的错误
  • 支持 Map 字面量语法:
fn init {
// 键必须是字面量
let m1 : Map[String, Int] = { "x": 1, "y": 2 }
let m2 : Map[Int, String] = { 1: "x", 2: "y" }
}

IDE更新

  • 修复了 IDE 在补全过程中 builtin package 中的方法会重复出现两次的 bug

  • 修复了 IDE 中缺少 Byte 相关的补全功能

构建系统更新

  • 添加对 internal 包的支持,这些包被放在名为 internal 的目录中。internal 包只能被以 internal 的父目录为根的包导入。 例如,如果有一个包的路径为 username/hello/x/internal/a,该 internal 包的父目录为 username/hello/x,那么只有包username/hello/x 或其子包(例如 username/hello/x/a)能够导入username/hello/x/internal/a,而username/hello/y则不能导入该包。

weekly 2024-06-11

· 阅读需 2 分钟

MoonBit更新

  • 【Wasm MVP】Wasm1 后端添加基于 Perceus 算法的引用计数支持

  • 【语法】throw raise try catch 均被保留为关键字

    • 为了即将添加的错误处理机制
  • 【Core】Listsorted_map被移动至core/immut

    • List被移动至core/immut/list包中,并被移除内置类型支持

    let a = @immut/list.List::Cons(1, Cons(2, Nil))


    • sorted_map被移动至core/immut/sorted_map包中
  • 【Core】JSON API被优化,以提高性能并适应新的Core API

    • 新的类型定义
// Types and methods
pub enum JsonValue {
Null
// 原为Boolean(Bool)
True
False
Number(Double)
String(String)
Array(Array[JsonValue])
Object(Map[String, JsonValue]) // 原为@map.Map
}
  • 【JS】Int64性能优化
    • 在 JS 后端上,Int64现编译到两个Int,解决原先编译到BigInt的性能问题。同时,JS 下Int64的 runtime 实现现移动到 core 标准库中,便于开源社区参与 review 和改进。

构建系统更新

  • moon.mod.json 和 moon.pkg.json 在开发过程中支持注释,但是在 publish 时不允许注释(只支持标准 JSON 格式)

IDE更新

  • 【LSP】函数补全增加参数名称显示 LSP.png

weekly 2024-06-03

· 阅读需 3 分钟

MoonBit更新

  • 类型标注增加了新的语法T? 来表示Option[T]
struct Cell[T] {
val: T
next: Cell[T]?
}

fn f(x : Cell[T]?) -> Unit { ... }

相当于

struct Cell[T] {
val: T
next: Option[Cell[T]]
}

fn f(x : Option[Cell[T]]) -> Unit { ... }

旧的Option[T]仍然兼容,但是推荐使用更简短的新语法。moonfmt也会将Option[T]格式化为T?

  • 核心库 API 整理工作继续进行
    • Iter包被合入了builtin包。现在使用Iter[T]不需要@iter.前缀
pub fn any[T](xs : Iter[T], predicate : (T) -> Bool) -> Bool {
// ^不需要@iter.
match xs.find_first(predicate) {
None => false
Some(_) => true
}
}
  • Stack包被移入moonbitlang/x
  • 移除了List包,以及各类数据结构的to_listfrom_list函数。对于数据结构间转换和中间的表示结构,推荐使用Iter[T]Array[T]
  • 性能提升
    • 编译器现在会在分离编译的阶段进行一部分的闭包转化,从而改进了编译性能,并且对 JavaScript 后端生成的代码在特定情况下也进行了闭包转化
    • Option[Bool], Option[Char], Option[Byte], Option[Unit] 这些类型使用32位整数表示,其中 None 对应的值为 -1, Some(x) 对应的值为 x; Option[Int] 类型在 wasm 后端使用 64 位整数表示,其中 None 对应的值为 0x1_0000_0000, Some(x) 对应的值为 x, Option[Int]在 JavaScript 后端使用 int | undefined 表示,其中 undefined 表示 None
  • abort行为变更
    • 为了解除Wasm程序对于非标准的spectest.print_char的依赖,正在重构错误输出功能。
    • abort将不会利用spectest.print_char打印错误信息,行为与panic相同,等待功能进一步完善。

插件更新

  • 【语言服务器】修复了内存泄露的问题

weekly 2024-05-27

· 阅读需 3 分钟

MoonBit 周报 Vol.42:核心库进行API整理工作、工具链持续完善

MoonBit更新

  • 【核心库 Breaking】核心库进行API整理工作
    • 所有immutable数据结构被放在immut路径下,如@immutable_hashmap.Map变为@immut/hashmap.Map
// Before
let a : @immutable_hashmap.Map[Int, Int] = @immutable_hashmap.make()
// After
let a : @immut/hashmap.Map[Int, Int] = @immut/hashmap.make()
  • 核心库中 Option[T] 类型性能优化
    • 在类型 T 是一个引用类型情况下,对于 Option[T] 类型的值,Some(v) 会被直接编译成 vNone 会在 wasm-gc 后端被编译成 ref.null ,在 JavaScript 后端被编译成 undefined,从而避免内存分配
  • 核心库中引入了 fn panic[T]() -> T 函数,这个函数可以用于在测试块中,其中测试的名字需要以 "panic" 开头:
test "panic test ok" {
panic() // 测试通过
}

test "panic test failed" {
() // 测试失败
}

IDE更新

  • 【VS Code插件】增加了testfor的代码片段 test片段 test.gif for片段 for.gif

构建系统更新

  • 【初始化】moon new 会自动对创建的项目进行版本控制初始化,目前支持 git
  • 【测试】现在可以指定对多个包进行测试
moon test -p a b c
moon test -p a -p b -p c

工具链更新

  • 【安装】现在可以指定版本号进行安装
# Mac与Linux用户
# 下载最新版
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
# 下载 bleeding 版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s bleeding
# 下载特定版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s 0.1.20240520+b1f30d5e1
# Windows用户
# 下载最新版
irm cli.moonbitlang.cn/install/powershell.ps1 | iex
# 下载特定版本
$env:MOONBIT_INSTALL_VERSION = "0.1.20240520+b1f30d5e1"; irm cli.moonbitlang.cn/install/powershell.ps1 | iex

weekly 2024-05-20

· 阅读需 3 分钟

MoonBit更新

  • 【Breaking Change】Array重命名为FixedArray@vec.Vec重命名为Array
// Before
fn init {
let array : @vec.Vec[Int] = [1, 2, 3]
}
// After
fn main {
let array : Array[Int] = [1, 2, 3]
}
  • 【语法】键值对(如Map HashMap等)增加模式匹配支持
    • 类型需实现op_get方法,其键为原生类型(Int Char String Bool等),值为Option[T]
    • 匹配时,键需为字面量
    • { "key": pat } 中,模式 pat 类型是 Option[T]None表示 "key"不存在,Some(p)表示 "key"存在,且 p 会被用于匹配这个键的值
    • 匹配键值对的模式都是开放的:未被匹配的键即使存在也会被忽略掉
    • 键值对模式会生成优化过的代码,每个键至多被查询一次
fn main {
let map = @map.Map::[ ("a", 1) ]
match map {
// 当 `map` 包含 "b" 时匹配,
// 并把 "b" 在 `map` 中的值绑定到 `y`
{ "b": Some(y) } => println(y)
// 当 `map` 不包含 "b" 而包含 "a" 时匹配,
// 并把 "a" 的值绑定到 `k`
{ "b": None, "a": Some(k) } => println(k)
// 编译器提示 { "b": None, "a": None } 的情况未被匹配到
}
// 输出:1
}
  • 【语法】允许在已知类型信息的情况下省略newtype构造器
type A Int

pub fn op_add(self : A, other : A) -> A {
self.0 + other.0 // 省略构造器
}

fn main {
A::A(0) + 1 |> ignore // 省略 1 的构造器
let _c : A = 0 + 1 + 2
}

构建系统更新

  • 配置文件选项统一为kebab-case(近期仍对snake_case保持兼容)
{
"is-main": true,
"test-import": []
}
  • 【Wasm,Wasm-GC】后端支持在moon.pkg.json中指定导出内存名称(默认为moonbit.memory)与编译选项(如-no-block-params以兼容binaryen工具链)
{ 
"link": {
"wasm": {
"export-memory-name": "custom_memory_name",
"flags": ["-no-block-params"]
},
}
  • moon check 增加 --deny-warn 选项,在有 warning 时视为失败,返回非0值
  • moon fmt 增加 --check选项,用于检查当前代码是否已被格式化

标准库更新

  • 增加实验性库moonbitlang/x,用于开发与测试API不稳定的包。moonbitlang/x中的包稳定后,我们会根据社区的意见,选取重要的包合入moonbitlang/core
    • num time uuid json5 均已移动至moonbitlang/x
  • Bytes API 变更,从Int迁移到了Byte类型:
fn Bytes::op_get(self : Bytes, index : Int) -> Byte
fn Bytes::op_set(self : Bytes, index : Int, value : Byte) -> Unit
fn Bytes::length(self : Bytes) -> Int
fn Bytes::make(len : Int, ~init : Byte = b'\x00') -> Bytes

weekly 2024-05-13

· 阅读需 4 分钟

MoonBit更新

  • 支持了构造器的 payload 中出现 mutable field,使用方式如下:
enum E {
C(mut ~x : Int, mut ~y : Int)
} derive(Debug)


fn swap_xy(x : E) -> Unit {
match x {
// `~y` 会绑定模式匹配前 `C` 中的 `y` 字段的值
// 当看到 `C(..) as c` 这种模式时,编译器知道 `c` 一定是构造器 `C`,
// 所以可以在分支内部用 `c.x`、`c.y` 直接访问 `C` 的字段
C(~y, ..) as c => {
// `c.x` 和 `c.y` 可以用于修改/读取 `C` 中最新的值
c.y = c.x
c.x = y
}
}
}

fn init {
let e : E = C(x=1, y=2)
debug(e) // C(x=1, y=2)
swap_xy(e)
debug(e) // C(x=2, y=1)
}

这个例子中的 swap_xy 函数对构造器 Cxy 两个 field 的值进行了交换,并且这个交换是 in-place 的,没有引入额外的内存分配

  • **数组字面量默认构建 vector。**对 Array literal 语法进行了重载,现在 Array literal 可以用来构造 Vector 或者 Array,具体的类型通过上下文决定,当上下文中类型信息不明确时,默认使用 Vector,比如
fn init {
let v = [1, 2, 3] // v has type @vec.Vec[Int]
let a : Array[_] = [1, 2, 3] // a has type Array[Int]
}
  • 报错信息中添加了错误代码,例如
./vec/sort.mbt:68:16-68:23 [E4021] The value identifier minimum is unbound.
./vec/sort_by.mbt:90:16-90:23 [E4021] The value identifier minimum is unbound.
./vec/vec.mbt:962:37-962:50 [E4020] Package "iter" not found in the loaded packages.
./vec/vec.mbt:963:3-963:13 [E4024] The type/trait @iter.Iter is not found.

IDE更新

  • 对构造器中的 labeled field 的 label 支持了 gotodef/gotoref/rename 等功能,例如 label.PNG

构建系统更新

  • 支持在 package 级别配置 warn list 与alert list
    • moon.pkg.json 中如下配置,可在编译时关闭对应的 warn 与 alter【其中 2alter_1alert_2 分别为编译器预设的 warn id (对于 Unused variable) 与用户自定义的 alert id】
{
"warn_list": "-2",
"alert_list": "-alert_1-alert_2"
}
  • -代表关闭对应 id 的 warn 与 alter,可用 moonc build-package -warn-help 查看预设的 warn

  • moon check|build|run|test 的默认后端由wasm切换为wasm-gc

  • moon test 默认执行模式由 release 修改为 debug

  • moon check|build|run|test支持自动安装依赖,而无需手动执行 moon install

  • moon doc --serve 支持指定地址与端口

-b, --bind <BIND> [default: 127.0.0.1]
-p, --port <PORT> [default: 3000]
  • 优化 moon 体积
平台优化前优化后
macOS arm647.3 MiB3.6 MiB
macOS x86_648.2 MiB4.1 MiB
Ubuntu x86_6414.0 MiB9.6 MiB
Windows x86_649.4 MiB4.9 MiB

工具链更新

  • moonrun 支持打印 backtrace, 使用样例: 使用 moon new hello 创建一个新项目,将 main/main.mbt 的内容替换为:
  fn bar() -> Unit {
abort("")
}

fn foo() -> Unit {
bar()
}

fn main {
foo()
}

执行 moon run main --debug,可观察到输出类似:

error: RuntimeError: unreachable
at $username/hello/main.bar.fn/1 (wasm://wasm/6fe99e5e:wasm-function[3]:0xe6)
at $username/hello/main.foo.fn/2 (wasm://wasm/6fe99e5e:wasm-function[4]:0xea)
at *init*/3 (wasm://wasm/6fe99e5e:wasm-function[5]:0xef)
at <anonymous>:9:22

weekly 2024-04-30

· 阅读需 6 分钟

MoonBit 更新

  • 新增JavaScript后端

目前MoonBit已新增对JavaScript的支持并带来前所未有的性能提升,在JS后端实现了超出Json5近8倍性能的优势。更详细的介绍可以看一下这篇文章:IDEA研究院编程语言MoonBit发布JavaScript后端,速度提升25倍

如果你想自己体验一下,可以点击:https://github.com/moonbit-community/benchmark-202404/tree/master/bench_json5

  • 现在MoonBit允许传递回调函数至FFI。但回调函数的参数和返回值类型目前只能是简单类型,如Int等。例子:

    // 使用示例:传递回调函数至外部
    fn set_callback(f : () -> Int) = "ffi" "set_callback"

    // 使用示例
    fn use_callback() -> Int = "ffi" "use_callback"

    test {
    let i = { val : 0 }
    set_callback(fn () {
    i.val += 1
    i.val
    })
    inspect(use_callback(), content="1")?
    inspect(use_callback(), content="2")?
    inspect(use_callback(), content="3")?
    inspect(use_callback(), content="4")?
    }

    let f

    export default {
    // 必要外部接口:将闭包转换为JS函数。其他运行时根据语言不同实现方式不同
    'moonbit:ffi': {
    make_closure: (funcref, context) => funcref.bind(null, context)
    },
    // 使用示例
    ffi: {
    set_callback: (func) => {
    f = func
    }, // 设置回调函数
    use_callback: () => f() // 使用回调函数
    }
    }
  • 修改显式实现 trait(extension method)的语法,允许显式写出要给哪个类型实现 trait

    // 为 `Trait` 的方法 `method` 提供默认实现
    impl Trait with method(...) { ... }

    // 给类型 `Type` 实现 `Trait` 的方法 `method`
    impl Trait for Type with method(...) { ... }

    // 带类型参数的情况
    impl[X] Trait for Array[X] with method(...) { ... }

    和之前的 fn Trait::method(...) 语法相比,新的语法允许显式写出实现 trait 的类型,签名信息更丰富、更清晰。由于写出了类型,编译器可以自动推断出方法的参数和返回值类型,不需要手动标注:

    trait MyTrait {
    f(Self) -> Option[Int]
    }

    // 无需标注 `self` 和返回值的类型
    impl MyTrait for Int with f(self) {
    // 编译器能自动推断出返回值的类型是 `Option[Int]`
    Some(self)
    }

  • 支持Bytes字面量

    Bytes字面量b"..." 会将双引号内的ASCII字符串转换为Bytes类型,字符串内支持十六进制和八进制转义。

     let b1 : Bytes = b"ASCII"
    let b2 : Bytes = b"\xFF\o000"

  • { x } 的二义性问题修复

现在{ x }会解析成只有一个x字段的struct,相当于{ x: x }。对于这种容易造成混淆的写法,编译器会发出警告。

IDE更新

  • 插件新增moonbit.autoUpdate的选项控制是否开启自动更新的提示
  • 插件支持多后端开发
    • 用户可以在vscode里选择不同的后端
    • 非当前后端的代码对比度会变低

plugins.gif

构建系统更新

  • 支持后端特定文件,这些文件的拓展名以 .wasm|wasm-gc|js.mbt结尾,例如:foo.wasm.mbtfoo.wasm-gc.mbtfoo.js.mbt。例如在 moon build --target js 中,只有普通的 .mbt 文件与 .js.mbt 才会参与构建。相应地,moon check|build|test、以及moonbitlang/core的链接修改为与后端相关。

  • moon.pkg.json 中的 ["link"]["js"]中新增 format 字段,用于指定输出的JavaScript模块格式,可能的值为 esm|cjs|iife,默认为 esm

    • esm模式下,使用export { x as y }语句导出
    • cjs模式下,使用exports.y = x导出
    • iife模式下,使用globalThis.y = x导出

    moon.pkg.json样例:

    {
"link": {
"js": {
"exports": [
"hello"
],
"format": "cjs"
}
}
}

  • moon test -u支持自动更新测试块中的多个inspect函数,以及添加 -limit 选项用于限制自动更新的最大迭代次数。

工具链更新

  • moonrun由wasmtime切换到v8,现在支持wasm-gc后端
    moon new hello
cd hello
moon run main --target wasm-gc
  • moon info 的更新
    • 支持对方法进行分组,方便对比不同数据结构的实现
    • 支持带标签的参数、默认参数和自动填充参数
type Map
impl Map {
debug_write[K : Debug, V : Debug](Self[K, V], Buffer) -> Unit
elems[K, V](Self[K, V]) -> List[V]
fold[K, V, T](Self[K, V], (T, V) -> T, ~init : T) -> T
from_array[K : Compare + Eq, V](Array[Tuple[K, V]]) -> Self[K, V]
// ...
}