相当于 Haskell 中具有停止条件的生成器

Eri*_*uld 3 haskell functional-programming generator

假设我想iterate step x0在 Haskell 中构建一个列表,但具有包含终止条件。所以在Python中这将是list(my_gen)例如

def my_gen():
    x = x0
    while not done(x):
        x = step(x)
        yield x
Run Code Online (Sandbox Code Playgroud)

编辑:如果我想包含,这应该yield x在循环之前有一个额外的x0。)

一种方法是编写我自己的takeWhileInclusive并说

takeWhileInclusive (not . done) . iterate step x0
Run Code Online (Sandbox Code Playgroud)

这是实现此目的的Haskell-y 方式(或Haskell -y 方式)吗?step x尝试为何时为真添加一些哨兵值done x然后使用似乎不自然takeWhile

特别是我正在考虑LeetCode上水问题最多的容器,并用类似的方法解决它

maxWith volume . smartSteps (0, n)
 where smartSteps = takeWhileInclusive (\(i,j) -> j - i > 1) . iterate step
Run Code Online (Sandbox Code Playgroud)

step增加i或减少j(或两者),根据哪个指数具有较高的线。

当然,在这里使用 j > i 很容易takeWhile,但我想考虑如何处理不存在自然的“你走得太远”条件,而只是“你已经完成”条件的情况。

编辑:这个问题已被标记为重复(我在问题中链接到的问题),但事实并非如此。问题不是如何写takeWhileInclusive,事实上问题明确地认为takeWhileInclusive是给定的。它是关于如何完成可能使用也可能不使用的任务takeWhileInclusive

che*_*ner 5

您可以使用unfoldr来生成序列:

unfoldr (\x -> if done x then Nothing else Just (x, step x)) x0
Run Code Online (Sandbox Code Playgroud)

例如,

> import Data.List
> step = (+1)
> done = (> 10)
> x0 = 0
> unfoldr (\x -> if done x then Nothing else Just (x, step x)) x0
[0,1,2,3,4,5,6,7,8,9,10]
Run Code Online (Sandbox Code Playgroud)

unfoldr调用其函数x0来启动。当函数返回时Nothingunfoldr停止。当函数返回时Just (x, y),它会追加x到结果中并再次调用该函数y

将您的生成器与 Python 实现进行比较unfoldr

def unfoldr(f, x):
    while True:
        if (y := f(x)) is None:
            return
        else:
            yield y[0]
            x = y[1]

list(unfoldr(lambda x: None if done(x) else (x, step(x)), x0))
Run Code Online (Sandbox Code Playgroud)