Dhall中自然数整数除法实现:寻求更惯用的解决方案
嘿,首先得夸夸你——能用Natural/fold搞定自然数除法还通过了所有测试,而且还根据自己的场景处理了除零返回0的情况,这已经很到位了!
先解释下你最初递归写法报错的原因:Dhall是严格的完全函数式语言,为了保证所有函数都能终止,它不允许直接递归定义函数(没法静态证明递归会终止)。所以你那种直接调用quotient自身的写法会被拒绝,必须借助Natural/fold这种结构化递归工具——因为自然数是归纳类型,fold是它的标准消去器,能保证递归一定会终止。
你的实现逻辑是完全正确的,不过可以调整得更符合Dhall的惯用风格,提升可读性:
let quotient = λ(n : Natural) → λ(m : Natural) → let DivResult = { quotient : Natural, remainder : Natural } in ( Natural/fold n DivResult ( λ(current : DivResult) → if Natural/isZero m then current else if Natural/lessThan current.remainder m then current else { quotient = current.quotient + 1 , remainder = Natural/subtract m current.remainder } ) { quotient = 0, remainder = n } ).quotient
这个版本和你的思路完全一致,只是做了这些小调整:
- 把中间结果类型命名为
DivResult,字段用quotient和remainder替代缩写的q/r,更直观 - 保持逻辑的扁平化,避免嵌套过多的
let
另外你提到没在Prelude里找到现成的整数除法函数,这是正常的:Dhall Prelude刻意没提供默认的除法实现,因为不同场景对除零的处理需求差异很大(有的需要抛出错误,有的返回0,有的期望Optional类型),把实现权交给用户反而更灵活。
你的实现完全满足自己的场景需求,而且逻辑严谨——本质上就是实现了欧几里得除法的商计算,完全没问题。如果之后需要调整除零行为,比如返回Optional Natural,只需要修改Natural/isZero分支的返回值即可。
内容的提问来源于stack exchange,提问作者stefanobaghino
相关产品推荐
相关产品推荐

