在时域中进行一些音频过滤时,我遇到了一个问题,我会用索引在迭代语言中解决。在Haskell中,编写算法似乎有点困难。好的,所以重点是:
[x1 x2 x3 | x4 x5 x6 | x7 x8 x9 x10 ...]
|y1 y2 y3 | y4 y5 y6 | ]
想象一下两个列表,上面一个是源,下面一个是目标。我在两个阵列上从左到右移动一个2x3字段大小的窗口,在这个例子中它是x4-x6和y4-y6。 y6即将获得一个函数的结果,该函数得到x4,x5,x6,y4和y5进行处理。 通常我会在haskell中使用递归函数执行此操作,但重点是,此函数计算y6是一个参数。它是具有单独算法的10种不同滤波器功能之一。 在一开始我只有x1来计算y1。在下一步中,我有x1,y2和y1来处理y2。第三步取x1,x2,x3,y1和y2产生y3。等等,直到y_n。 目前,我一直坚持如何做到这一点。
编辑:更详细一点
现在,这里的函数就像在旧的C中读取的那样:
void processArray(int[] in, int[] out, int count, int (*filterFunction)(int, int, int, int, int)) {
int index;
for (int index = 0; index < count; index++) {
out[index] =
filterFunction(
index - 2 >= 0 ? in[index-2] : 0,
index - 1 >= 0 ? in[index-1] : 0,
in[index],
index - 2 >= 0 ? out[index-2] : 0,
index - 1 >= 0 ? out[index-1] : 0,
}
}
答案 0 :(得分:5)
您需要使用本地递归来构建此列表。您想要在5个输入列表中映射一些函数f
,因此选择的工具是zipWith5
。第一个列表基本上是0 : 0 : input
,第二个列表基本上是0 : input
,第三个列表只是input
,第四个列表只是0 : 0 : out
,第五个列表是0 : out
1}}。
processArray :: (Int -> Int -> Int -> Int -> Int -> Int) -> [Int] -> [Int]
processArray f input =
let out = zipWith5 f (0 : 0 : input)
(0 : input)
input
(0 : 0 : out)
(0 : out)
in out
这与Fibonacci序列非常相似
fibs = 1 : 1 : zipWith (+) fibs (drop 1 fibs)
在CPU性能方面非常有效地生成所有Fibonacci值的列表,但是根据您的使用方式可能会耗尽所有RAM。
就困难而言,这只是使用递归,列表缺点和zipWith5
来定义。只要input
,它就会生成一个列表,这意味着理论上它可以是无限的。它不需要知道列表的长度,也不需要在每个阶段检查索引。它也会懒洋洋地产生这些价值。总的来说,我认为这比C版本简单得多。