我在互联网上找到了解决方案,但我不确定它是什么。结果是正确的。
foldr (\n acc -> (n*10):acc) []
有人能解释一下这个功能的步骤吗? 这应该将列表中的所有元素乘以10。
谢谢
答案 0 :(得分:4)
foldr
函数可以定义如下:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
它采用类型a
的值列表和类型b
的单个值 - 累加器。它从列表中获取项目,将它们与累加器组合并返回最终值。在您的情况下,a
是一些数字,b
实际上也是一个数字列表。您的函数的完整类型为Num a => [a] -> [a]
。
考虑将您的函数应用于列表[1,2,3]
:
foldr (\n acc -> (n*10):acc) [] [1,2,3] ~~>
(\n acc -> (n*10):acc) 1 (foldr (\n acc -> (n*10):acc) [] [2,3]) ~~>
(1*10) : foldr (\n acc -> (n*10):acc) [] [2,3] ~~>
10 : foldr (\n acc -> (n*10):acc) [] [2,3] ~~>
10 : (\n acc -> (n*10):acc) 2 (foldr (\n acc -> (n*10):acc) [] [3]) ~~>
10 : (2*10) : foldr (\n acc -> (n*10):acc) [] [3]
10 : 20 : foldr (\n acc -> (n*10):acc) [] [3] ~~>
10 : 20 : (\n acc -> (n*10):acc) 3 (foldr (\n acc -> (n*10):acc) [] []) ~~>
10 : 20 : (3*10) : foldr (\n acc -> (n*10):acc) [] [] ~~>
10 : 20 : 30 : foldr (\n acc -> (n*10):acc) [] [] ~~>
10 : 20 : 30 : []
答案 1 :(得分:2)
如果您不允许使用map
因为这是作业,那么您可能也不允许使用foldr
。使用foldr
将列表中的每个元素乘以10将是一种相当愚蠢的方式(除了作为学习练习)。作为一般规则:
让我们编写自己的函数。该函数将获取一个数字列表,并返回一个列表。如果您想使用Int
s,那么:
myFunction :: [Int] -> [Int]
(更好的是,不要在10中进行硬编码,你可以让它成为输入参数。我会把它作为练习留给你。)
我们可以使用递归来实现这个功能。使用递归时,首先要问自己“什么是基础(最简单)的情况”。那么,这将是一个空列表。如果我们得到一个列表,那就没什么可做的,所以我们只返回空列表。
myFunction [] = []
现在,如果我们的列表非空,该怎么办?好吧,我们可以将第一个元素乘以10,并将其与在列表的其余部分上运行myFunction
的结果相连接。
myFunction (x:xs) = x*10 : myFunction xs