新手技术问询:在Haskell中能否存储已被移除的值?
关于Haskell中保留被移除值的解决方案
嘿,作为Haskell新手,能看出来你在尝试实现信用卡号的校验逻辑(大概率是Luhn算法对吧?),针对你问的「能不能存储已被移除的值」——当然可以!
你当前的代码里,checklength函数用init(x)去掉了信用卡号的最后一位,但没有保留这个值,而如果是做Luhn校验的话,这最后一位其实是校验位,后续的校验步骤肯定需要用到它。在Haskell这种纯函数式语言里,我们没有可变变量,但可以通过传递参数、封装元组的方式来“保留”这个被移除的值,下面给你具体的修改思路和代码示例:
核心修改思路
把被移除的最后一位(校验位)和剩下的数字列表一起传递给后续处理函数,而不是直接丢掉它。
步骤1:调整处理函数的参数
首先修改doubleall,让它能接收校验位和需要处理的数字列表:
-- 新增校验位参数,后续finalcheck需要用它来完成最终校验 doubleall :: Integer -> [Integer] -> String doubleall checkDigit xs = finalcheck checkDigit $ final $ double (reverse xs)
步骤2:修改checklength函数,保留并传递校验位
原来的checklength只传递了init(x),现在我们把last x(被移除的最后一位)也传进去:
checklength :: [Integer] -> String checklength x | length x >= 13 && length x <= 16 = doubleall (last x) (init x) | otherwise = "Not valid length of credit card number"
额外优化:优化intolist函数
你当前的intolist用++拼接列表,效率比较低(每次++都要遍历整个列表),可以改成用:构建逆序列表,后续如果需要正序再反转,或者直接适配你的reverse逻辑:
intolist :: Integer -> [Integer] intolist 0 = [] intolist x = x `mod` 10 : intolist (x `div` 10) -- 这个版本生成的是数字的逆序列表,比如intolist 1234会得到[4,3,2,1] -- 这样后续double函数里的reverse可以去掉,直接用xs即可,能省一步操作
为什么这样可行?
Haskell是纯函数式语言,没有像命令式语言那样的可变存储,但我们可以通过函数参数传递或者封装元组/自定义数据类型的方式,把需要保留的值携带到后续的计算步骤中。本质上是把“存储”转化为“传递”,这也是纯函数式编程里处理这类问题的常规思路。
内容的提问来源于stack exchange,提问作者Car
相关产品推荐
相关产品推荐

