Haskell中的反向函数行为


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

累加器通过在操作前连续添加运算来增长,使数字以适当的顺序结束。

最新更新