有人能解释一下haskell的功能吗?

时间:2014-01-19 20:45:09

标签: haskell fold

我在互联网上找到了解决方案,但我不确定它是什么。结果是正确的。

foldr (\n acc -> (n*10):acc) []

有人能解释一下这个功能的步骤吗? 这应该将列表中的所有元素乘以10。

谢谢

2 个答案:

答案 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将是一种相当愚蠢的方式(除了作为学习练习)。作为一般规则:

  • 如果您想对列表中的每个元素执行某些操作,并获得列表作为结果,那么您可能需要某种 map 函数。
  • 如果您想对列表中的每个元素执行某些操作,并获得单值作为结果,那么您可能需要一个 fold 函数。 / LI>

让我们编写自己的函数。该函数将获取一个数字列表,并返回一个列表。如果您想使用Int s,那么:

myFunction :: [Int] -> [Int]

(更好的是,不要在10中进行硬编码,你可以让它成为输入参数。我会把它作为练习留给你。)

我们可以使用递归来实现这个功能。使用递归时,首先要问自己“什么是基础(最简单)的情况”。那么,这将是一个空列表。如果我们得到一个列表,那就没什么可做的,所以我们只返回空列表。

myFunction [] = []

现在,如果我们的列表非空,该怎么办?好吧,我们可以将第一个元素乘以10,并将其与在列表的其余部分上运行myFunction的结果相连接。

myFunction (x:xs) = x*10 : myFunction xs