Haskell自定义BigNumber实现两数相加出现类型错误如何解决?
报错原因
zipWith用法错误:Haskell 中函数调用优先级高于运算符,你写的zipWith + ...会被编译器解析为尝试对zipWith函数本身做加法运算,完全不符合zipWith的参数要求。zipWith的第一个参数是要逐位应用的二元函数,加法作为参数需要包裹在括号中,正确写法为zipWith (+)。map参数顺序错误:map第一个参数是要作用到列表每个元素的函数,第二个才是待遍历的列表。你写的map (read a)相当于直接对整个[String]类型的a调用read,本身就是类型错误,正确写法为map read a,将read作用到a的每个字符串元素上转换为整数。- 类型匹配缺失:即使修正前两个问题,逐位相加得到的是
[Int]类型,而函数要求返回BigNumber也就是[String],还需要将计算后的整数转回字符串;此外当前逻辑没有处理进位,也没有考虑两个输入列表长度不同的情况,不符合大数加法的实际需求。
代码修复
最简可运行版本(仅解决编译报错,未处理进位和长度差异)
somaBN :: BigNumber -> BigNumber -> BigNumber somaBN a b = map show $ zipWith (+) (map read a) (map read b)
完整大数加法版本(处理进位、长度差异)
somaBN :: BigNumber -> BigNumber -> BigNumber somaBN a b = reverse $ map show $ addWithCarry 0 reversedA reversedB where -- 转成整数列表后反转,从最低位开始计算 reversedA = reverse $ map read a :: [Int] reversedB = reverse $ map read b :: [Int] -- 带进位的加法逻辑 addWithCarry carry [] [] = if carry == 0 then [] else [carry] addWithCarry carry xs [] = addWithCarry carry xs [0] addWithCarry carry [] ys = addWithCarry carry [0] ys addWithCarry carry (x:xs) (y:ys) = let total = x + y + carry newCarry = total `div` 10 currentDigit = total `mod` 10 in currentDigit : addWithCarry newCarry xs ys
该版本实现了标准大数加法逻辑:先反转列表从最低位开始计算,长度不一致时自动补0,计算过程中维护进位,所有位计算完成后仍有进位则额外补最高位,最后将结果反转回高位在前的常规大数表示格式。
内容的提问来源于stack exchange,提问作者Francisca Almeida
相关产品推荐
相关产品推荐

