我正在努力使用Haskell,以及使用递归迭代事物的想法。
例如,如何
// this might seem silly but I need to do it
list1 = empty list
list2 = list of numbers
for i from 0 to N // N being a positive integer
for each number in list2
if number == i, add to list1
转化为“功能范式”?任何指导都将不胜感激。
答案 0 :(得分:10)
很抱歉,但我无法使用更好的算法...
let goodNumber n = (0 <= n && n < N)
let list1 = sort (filter goodNumber list2)
编辑:事后看来,这有点过分,因为OP首先试图实施排序算法。
答案 1 :(得分:9)
一步一步走:
list2 = list of numbers
我们将此视为给定,因此list2
仍然只是一个数字列表。
for i from 0 to N // N being a positive integer
在Haskell中执行此操作的正确方法通常是使用列表。懒惰意味着只有在使用时才会计算值,因此遍历从0到N的列表最终与您在此处的循环相同。所以,只需[0..n]
即可;我们只需要弄清楚如何处理它。
for each number in list2
鉴于“为每个人”,我们可以推断出我们需要在这里遍历整个list2
;我们用它做什么,我们还不知道。
if number == i, add to list1
我们正在构建list1
,所以理想情况下我们希望这是表达式的最终结果。这也意味着在每个递归步骤中,我们希望结果是我们“到目前为止”的list1
。要做到这一点,我们需要确保随着时间的推移传递每个步骤的结果。
所以,深入了解它:
filter
函数查找列表中与某个谓词匹配的所有元素;我们将在这里使用filter (== i) list2
来查找我们所追求的内容,然后将其附加到上一步的结果中。所以每个步骤都是这样的:
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
处理内循环。向后退一步,我们需要为列表i
中的每个值[0..n]
运行此值,并在每一步传递list1
值。这正是折叠函数的用途,在这种情况下,step
正是我们左折所需的:
list2 :: (Num a) => [a]
list2 = -- whatever goes here...
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
list1 :: (Num a) => a -> [a]
list1 n = foldl step [] [0..n]
如果您想知道递归的位置,filter
和foldl
都在为我们做这件事。根据经验,当有更高级别的函数为你做时,通常最好避免直接递归。
也就是说,这里的算法在很多方面都是愚蠢的,但我不想进入那个因为它似乎会分散你的实际问题而不是它会有所帮助。
答案 2 :(得分:0)
let list1 = sort [a | a<-list2, a>=0, a<=N]
a<-list2
获取每个list2的数量
a>=0, a<=N
检查所选数字是否符合所有这些条件
如果满足条件,则将a放入新列表中
一旦检查了list2的所有元素并将其放入新列表中,我们就此进行排序
结果列表分配给list1