我正在尝试使用foldr函数在Haskell中定义一个函数:
fromDigits :: [Int] -> Int
此函数获取Ints列表(每个Ints范围从0到9)并转换为单个Int。例如:
fromDigits [0,1] = 10
fromDigits [4,3,2,1] = 1234
fromDigits [2,3,9] = 932
fromDigits [2,3,9,0,1] = 10932
无论如何,使用显式递归甚至使用zipWith来定义它都没有问题:
fromDigits n = sum (zipWith (*) n (map ((^)10) [0..]))
但现在我必须使用折叠器来定义它,但我不知道如何获得10的能力。我拥有的是:
fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs
如何让它们减少?我知道我可以从(长xs - 1)开始但是那么呢?
最好的问候
答案 0 :(得分:3)
关于foldr
的好处是它可视化非常容易!
foldr f init [a,b, ... z]
≡ foldr f init $ a : b : ... z : []
≡ a`f b`f`... z`f`init
≡ f a (f b ( ... (f z init)...)))
如您所见, j -th列表元素用于{em> j 连续调用f
。头元素仅传递一次到函数的左侧。对于您的应用程序,head元素是最后一位数字。这应该如何影响结果?好吧,它只是添加到结果中,不是吗?
15 = 10 + 5
623987236705839 = 623987236705830 + 9
- 很明显。那么问题是,你如何照顾其他数字?好吧,要使用上述技巧,首先需要确保在携带的子结果的最后位置有一个0。 0不是来自提供的数字!你如何添加这样的零?
现在应该给予足够的暗示。
答案 1 :(得分:3)
你快到了那里:
你的
fromDigits xs = foldr(\ x acc - >(x * 10 ^(???))+ acc)0 xs
是一个有两点变化的解决方案:
fromDigits = foldr(\ x acc - > acc * 10 + x)0
(顺便说一下,我在每一方都遗漏了xs
,这是没有必要的。
另一种选择是
fromDigits = foldl(\ x acc - > read $(show x)++(show acc))0
答案 2 :(得分:2)
诀窍是,你不需要每次从头开始计算10的幂,你只需要根据之前的10次幂计算它(即乘以10)。好吧,假设你可以反转输入列表。
(但你上面给出的列表已经是相反的顺序了,所以你可以说你应该能够重新反转它们,然后说你的函数以正确的顺序取一个数字列表。如果没有,那么只需要除以10而不是乘以10。)