我想删除没有特定属性的第一个元素。 例如,如果我的属性定义为...
greaterOne :: Num a=>Ord a=>a->Bool
greaterOne x = x > 1
然后函数filterFirst
应该给我这个......
filterFirst greaterOne [5,-6,-7,9,10]
>> [5,-7,9,10] //removes first element that is not greater than one
这是我的尝试......
filterFirst :: (a->Bool)->[a]->[a]
filterFirst p [] = []
filterFirst p (x:y:xs)
|p x = filterFirst p xs
|otherwise = y:xs
有人能帮助我吗?
答案 0 :(得分:6)
了解您的尝试:[]
被发送到[]
(这是正确的)。如果列表中包含至少两个元素(x:y:xs
),则您的函数会测试x
,会抛出x
和y
并继续过滤test 传递(绝对不是你想要的),并抛出x
并在测试失败时停止(这是正确的)。一个包含单个元素错误的列表,以及具有奇数个元素的许多其他列表(这都是错误的,并且是正确答案的线索)。
让我们一步一步地完成正确的实施。正如您所写,我们希望filterFirst
在a
和a
列表中使用谓词,并返回另一个a
列表:
filterFirst :: (a -> Bool) -> [a] -> [a]
谓词类型a -> Bool
无法细分,但[a]
可以:可以有空列表[]
和非空列表x:xs
,并且应该有每个案例:
filterFirst p [] = ...
filterFirst p (x:xs) = ...
在“基本情况”[]
中,没有任何内容可供过滤,因此我们希望这是[]
,这就是您所写的内容。由于此处未使用p
,因此您可以使用p
替换_
:
filterFirst _ [] = []
但你没必要。
我们想要对x:xs
做什么取决于p x
的值。如果p x
成立,我们需要一个以x
开头的列表。此列表的尾部应为xs
,但删除了第一个失败元素。如果p x
失败,我们要抛弃x
(第一个失败元素)并保留xs
(第一个失败元素之后的列表)。所以:
filterFirst p (x:xs)
| p x = x:filterFirst p xs
| otherwise = xs
这涵盖了所有可能性,所以我们已经完成了!
根据dfeuer的评论编辑。
答案 1 :(得分:4)
您可以滥用deleteBy
。
> deleteBy (>) 1 [5, -6, -7, 9, 10]
[5,-7,9,10]
......更一般地说:
filterFirst p = deleteBy (const p) undefined