You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haskell中定义可交换的自然数乘法?

解决Haskell自然数乘法中的非穷尽模式错误

首先,咱们先拆解你遇到的问题:Non-exhaustive patterns in function natPlus这个错误,本质是你的natPlus函数没有覆盖所有可能的参数组合,导致递归过程中触发了未定义的情况。

先看你写的natPlus代码:

natPlus :: Nat -> Nat -> Nat
natPlus Z a = a
natPlus (S a) (S b) = natPlus a (S (S b))

这个函数只处理了两种场景:

  • 第一个参数是Z,第二个是任意Nat
  • 第一个参数是S a,第二个是S b

但完全漏掉了**第一个参数是S a,第二个参数是Z**的情况!当你计算natMult (S (S Z)) (S (S Z))时,乘法的递归逻辑必然会触发这个未处理的组合,所以直接抛出了异常。

第一步:修正natPlus函数

自然数加法的标准递归逻辑应该是:

  • 0加任何数等于该数(你这部分是对的)
  • 一个后继数加另一个数,等于“另一个数加上该后继数的前驱”的后继(也就是S a + b = S (a + b))

按照这个逻辑,正确的natPlus应该写成:

natPlus :: Nat -> Nat -> Nat
natPlus Z a = a
natPlus (S a) b = S (natPlus a b)

这样不管第二个参数是Z还是S b,都能被正确匹配到,彻底解决非穷尽模式的问题。

第二步:实现正确的natMult函数

自然数乘法的递归逻辑是:

  • 0乘任何数都等于0
  • 后继数乘另一个数,等于“另一个数加上前驱数乘该数”(也就是S a * b = b + (a * b))

基于修正后的natPlus,我们可以写出正常工作的natMult:

natMult :: Nat -> Nat -> Nat
natMult Z _ = Z
natMult (S a) b = natPlus b (natMult a b)

现在测试你之前的例子:

Prelude> natMult (S (S Z)) (S (S Z))
S (S (S (S Z)))  -- 对应自然数4,完全符合预期

补充:原natPlus的问题根源

你原来的natPlus试图通过同时递减两个参数来实现加法,但这种方式只适用于两个参数都是后继数的场景,当其中一个参数变为Z时,就没有对应的模式匹配项了——这就是非穷尽模式错误的核心原因。而标准的加法递归只解构第一个参数,不管第二个参数的形态,自然能覆盖所有可能的输入组合。

内容的提问来源于stack exchange,提问作者user5775230

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:15:59