解决这个问题的更好方法是建立一个 10 次幂的列表。这很简单,使用iterate
:
powersOf :: Num a => a -> [a]
powersOf n = iterate (*n) 1
然后,您只需将这些 10 的幂乘以它们在数字列表中的各自值。使用 很容易做到这一点zipWith (*)
,但您必须首先确保它的顺序正确。这基本上只是意味着您应该重新排序您的数字,以便它们按数量级降序而不是升序:
zipWith (*) (powersOf 10) $ reverse xs
但我们希望它返回一个Integer
, not ,所以Int
让我们通过 amap fromIntegral
zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
剩下的就是总结它们
fromDigits :: [Int] -> Integer
fromDigits xs = sum $ zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
或者对于无积分的粉丝
fromDigits = sum . zipWith (*) (powersOf 10) . map fromIntegral . reverse
现在,您还可以使用折叠,它基本上只是一个纯 for 循环,其中函数是您的循环体,初始值是初始状态,您提供的列表是您正在循环的值. 在这种情况下,您的状态是一个总和以及您所使用的电源。我们可以创建自己的数据类型来表示这一点,或者我们可以只使用一个元组,第一个元素是当前的总数,第二个元素是当前的幂:
fromDigits xs = fst $ foldr go (0, 1) xs
where
go digit (s, power) = (s + digit * power, power * 10)
这大致相当于 Python 代码
def fromDigits(digits):
def go(digit, acc):
s, power = acc
return (s + digit * power, power * 10)
state = (0, 1)
for digit in digits:
state = go(digit, state)
return state[0]