Haskell foldWhile还是reduceWhile没有列表功能?

use*_*904 4 algorithm haskell functional-programming

我正在寻找一种类似于"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
Run Code Online (Sandbox Code Playgroud)

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

(cond 1 num) && func x num -> num'
(cond 1 num') && func x num' -> num''
(cond 1 num'') && func x num'' -> num'''
...
Run Code Online (Sandbox Code Playgroud)

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

任何帮助将不胜感激,提前谢谢.

bhe*_*ilr 6

我想你想要iteratetakeWhile:

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

iterateWhile :: (a -> a) -> (a -> Bool) -> a -> [a]
iterateWhile func cond = takeWhile cond . iterate func
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你想用它作为

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"
Run Code Online (Sandbox Code Playgroud)

你可以用折叠来做到这一点,但是为什么你已经有这个解决方案呢?如果评估条件与生成值是分开的,那么将这两个问题分开,而不是试图将它们联系在一起.这是做什么的iterateWhile.由于它被懒惰地评估,这只会生成值,直到找到一个不满足条件的值,并且它只需要一个循环来执行此操作.

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

firstWhere :: (a -> a) -> (a -> Bool) -> a -> a
firstWhere func cond = head . dropWhile cond . iterate func
Run Code Online (Sandbox Code Playgroud)