digits :: Int -> [Int]
digits n = reverse (x)
where x
| n < 10 = [n]
| otherwise = (mod n 10) : (digits (div n 10))
*ghci> digits 1234 = [3,1,2,4]*
digits' :: Int -> [Int]
digits' n = (x)
where x
| n < 10 = [n]
| otherwise = (mod n 10) : (digits' (div n 10))
*ghci>digits' 1234 = [4,3,2,1]*
根据我的理解,digits 1234
的评价应该是[1,2,3,4]
。但我似乎漏掉了什么。有人能解释一下吗?
问题是digits
在每个递归调用中反转字符串,而不仅仅是在外部级别反转一次。试试digits x = reverse (digits' x)
(或等价的digits = reverse . digits'
),看看是否可以解释其中的差异。
尽管amalloy给出了很好的答案,但这里有一种方法可以在不涉及reverse
库函数的情况下按预期顺序获得数字。
我们使用了一个常见的技巧,将结果累加到递归调用的一些额外参数中(">累加器"),这里标记为dgs
。
还使用divMod
库函数,该函数返回一个既包含商又包含余的对。
digits :: Int -> [Int]
digits n = go [] n
where
base = 10
go dgs k = if (k < base) then (k:dgs)
else let (q,r) = divMod k base
in go (r:dgs) q
累加器通过在操作前连续添加运算来增长,使数字以适当的顺序结束。