快速上手
本指南带你从一个空的 MoonBit 模块出发,写出对 arithmetic 每个层级各使用一次的代码。core 教程在此基础上继续,给出完整的任务。
安装与导入
把本包添加到 moon.mod:
moon add Luna-Flow/arithmetic@0.5.0
在每个使用它的包的 moon.pkg 中导入它,并使用 Luna Flow 代码约定的别名:
import {
"Luna-Flow/arithmetic" @lf_arith,
}
如果还需要 Ring 或 Field 等代数 trait,请添加 Luna-Flow/luna-generic,别名为 @lf_alg。
依赖能力,而非类型
针对函数所用到的 trait 来编写它。Add 和 Mul 是 MoonBit 的运算符 trait;Sqrt 来自本包:
fn[T : Add + Mul + @lf_arith.Sqrt] norm2(x : T, y : T) -> T {
@lf_arith.Sqrt::sqrt(x * x + y * y)
}
test "norm" {
inspect(norm2(3.0, 4.0), content="5")
}
norm2 接受 Float、Double,以及你自己实现了这三个 trait 的任何类型。
让失败显式化
检查 trait 返回 Result。传入一个 ArithmeticContext;原生实例不会读取它,但十进制后端会:
test "checked division" {
let ctx = @lf_arith.ArithmeticContext::decimal64()
inspect(@lf_arith.DivChecked::div_checked(1.0, 8.0, ctx).unwrap(), content="0.125")
match @lf_arith.DivChecked::div_checked(1.0, 0.0, ctx) {
Ok(_) => fail("unexpected quotient")
Err(e) => inspect(e.message, content="division by zero")
}
}
读取诊断
上下文 trait 还会返回诊断。把 转换为 Float 会丢失最后一位,结果会如实反映这一点:
test "contextual conversion" {
let ctx = @lf_arith.ArithmeticContext::new(24)
let out : @lf_arith.ArithmeticOutcome[Float] = @lf_arith.IntegralContextual::from_int_contextual(
16_777_217, ctx,
).unwrap()
inspect(out.value, content="16777216")
inspect(out.diagnostics.inexact, content="true")
}
Float 和 Double 的大多数上下文运算不检测舍入;API 页说明了哪些会检测。