4

我正在寻找一种类似于“foldWhile”的haskell函数或模式,除了它使用函数输出而不是折叠列表之外..一些代码可能会更好地解释它。

简化和伪:

nums :: [Integer]
nums = [1]

cond :: v -> [Integer] -> Bool
cond v ls = elem v ls

func :: x -> ls -> [Integer]
func x ls = x `some_op` ls

我需要一种应用模式,例如:

(cond 1 num) && func x num -> num'
(cond 1 num') && func x num' -> num''
(cond 1 num'') && func x num'' -> num'''
...

一旦 cond 返回 False,产生最后一个 num。

任何帮助将不胜感激,在此先感谢。

4

1 回答 1

6

我认为您想要iterateand的组合takeWhile

iterate :: (a -> a) -> a -> [a]
takeWhile (a -> Bool) -> [a] -> [a]

iterateWhile :: (a -> a) -> (a -> Bool) -> a -> [a]
iterateWhile func cond = takeWhile cond . iterate func

在您的情况下,您希望将其用作

lastWhere :: (a -> a) -> (a -> Bool) -> a -> a
lastWhere func cond = last . iterateWhile func cond

main = do
    let x = lastWhere (+1) (<10) 1
    print x
    -- prints "9"

您可能可以通过折叠来做到这一点,但是当您已经有了这个解决方案时,为什么还要麻烦呢?如果评估条件与生成值是分开的,那么将这两个关注点分开,而不是试图将它们联系在一起。这就是这样iterateWhile做的。由于它是惰性求值的,因此它只会生成值,直到找到不满足条件的值,并且只需要一个循环即可。

由于iterateWhile生成了所有满足该条件的元素列表,因此您可以简单地获取最后一个元素。如果你需要第一个失败的元素,我会做

firstWhere :: (a -> a) -> (a -> Bool) -> a -> a
firstWhere func cond = head . dropWhile cond . iterate func
于 2013-11-07T20:44:04.143 回答