我遇到了一种模式,我从一个种子值开始x
,在每一步生成一个新的种子值和一个要输出的值。我想要的最终结果是输出值列表。这可以用以下函数表示:
my_iter :: (a -> (a, b)) -> a -> [b]
my_iter f x = y : my_iter f x'
where (x',y) = f x
使用它的一个人为的例子是生成斐波那契数:
fibs:: [Integer]
fibs = my_iter (\(a,b) -> let c = a+b in ((b, c), c)) (0,1)
-- [1, 2, 3, 5, 8...
我的问题是我有一种感觉,很可能有一种更惯用的方式来做这种事情。我的功能有哪些惯用的替代方法?
我现在唯一能想到的都是iterate
前奏曲中的,但它们有一些缺点。
一种方法是先迭代,然后再映射
my_iter f x = map f2 $ iterate f1 x
where f1 = fst . f
f2 = snd . f
但是,如果没有自然的方法将 f 拆分为单独的 f1 和 f2 函数,这可能看起来很难看。(在人为的斐波那契案例中,这很容易做到,但在某些情况下,生成的值不是种子的“独立”函数,因此拆分事物并不那么简单)
另一种方法是将“输出”值与种子一起元组,并使用单独的步骤将它们分开(有点像用于排序的“施瓦茨变换”):
my_iter f x = map snd . tail $ iterate (f.fst) (x, undefined)
但这似乎很奇怪,因为我们必须记住忽略生成的值以获取种子((f.fst)位)并添加我们需要一个“未定义”值作为第一个虚拟生成值。