如果我正确地解释了您的问题,那么您是说您想要一种将函数应用于索引列表而不是一次单个索引的方法。
我能做到的最简单的方法是创建另一个函数,
deleteElems
而不是deleteElem
(注意尾随的s
.)
deleteElems
将是类型[Int] -> [a] -> [a]
,它将调用每个索引。
注意:请参阅底部的更新以获取正确的解决方案(我将这部分留在此处,以便其他人可以从我最初解决问题的尝试中学习以及为什么它不正确。)
这是一种方法:
deleteElems xs zs = foldr (\x z -> deleteElem x z) zs xs
可以缩短为:
deleteElems xs zs = foldr deleteElem zs xs
Prelude> deleteElems [2,3] [1..10]
[1,4,5,6,7,8,9,10]
或从您的示例中:
Prelude> map (deleteElems [2,3]) [["hello", "whatever", "foo", "bar"], ["hello", "whatever", "foo", "bar"], ["hello", "whatever", "foo", "bar"], ["hello", "whatever", "foo", "bar"]]
[["hello","bar"],["hello","bar"],["hello","bar"],["hello","bar"]]
deleteElems
用于foldr
重复调用deleteElem
以xs
从中删除索引zs
。有关 的更深入解释foldr
,请参阅foldr 如何工作?.
更新:
根据评论,上面的实现deleteElems
实际上是不正确的,因为当给定一个索引列表时,比如说[2,4,6]
,它将首先删除 index 2
,返回一个新列表,然后删除新4
列表上的索引并返回一个更新的列表,然后删除更新的索引列表。这个过程不是可交换的,这意味着改变索引的顺序,或者给出索引不会做同样的事情。6
deleteElems
[6,4,2]
我使用以下函数获得预期行为(从原始列表中删除给定索引)的一种方法:intersect
Data.List
deleteElems xs zs = foldr1 intersect $ map ($ zs) $ map deleteElem xs
这个新版本deleteElems
使用中的deleteElem
每个索引来应用xs
,创建一个包含length xs
多个函数列表的列表,这些deleteElem
函数列表是针对每个特定索引的。然后map ($ zs)
将每个柯里deleteElem
化函数应用于zs
,产生列表列表,其中每个内部列表仅deleteElem
应用于索引和 之一zs
。最后,我们使用intersect
fromData.List
来查找删除了所有正确元素的列表。
另外,我仍然绝对推荐查看foldr 是如何工作的?.