我碰到過一種模式,我從種子值x
開始,並在每一步生成一個新的種子值和一個要輸出的值。我期望的最終結果是輸出值的列表。如果「輸出」值與迭代的值不同,前奏的迭代的替代方法是什麼?
my_iter :: (a -> (a, b)) -> a -> [b]
my_iter f x = y : my_iter f x'
where (x',y) = f x
並使用此會產生Fibonacci數的一個人爲的例子:
fibs:: [Integer]
fibs = my_iter (\(a,b) -> let c = a+b in ((b, c), c)) (0,1)
-- [1, 2, 3, 5, 8...
我的問題是,我有這種感覺,有非常這可以通過下面的函數來表示可能是更習慣於這樣做的方式。什麼是我的功能的慣用替代方案?
我現在能想到的唯一一個涉及Prelude的iterate
,但它們有一些缺點。
的一種方法是首先遍歷和地圖後
my_iter f x = map f2 $ iterate f1 x
where f1 = fst . f
f2 = snd . f
然而,這看起來很醜陋,如果沒有分裂成˚F單獨F1和F2的功能自然的方式。 (在設計好的斐波那契情況下,這很容易做到,但是在某些情況下,生成的值不是種子的「獨立」功能,因此它不是那麼容易分割的東西)
另一種方法是將元組「輸出」的價值觀與種子一起,並使用單獨的步驟將它們分開(有點像「的Schwartzian變換」排序的東西):
my_iter f x = map snd . tail $ iterate (f.fst) (x, undefined)
但這似乎奇怪,因爲我們要記住忽略生成的值以獲得種子(第(f.fst)位)並添加我們需要的第一個虛擬生成值的「未定義」值。
一個有趣的方面是,如果你把它看作一個(最大的,最簡單的,最簡單的,最簡單的),那麼'Maybe(a,b)'部分來自'Maybe(a,_)'是'[a]展開)固定點。 @missingno要求的版本只是'unfoldr',用於'Stream a',其基礎函數是'(a,_)'。 Prelude'unfoldr'中額外的'Nothing'只是涵蓋了你想停止生成你的列表的情況,但是這絕不會發生在這裏。 – copumpkin
@copumpkin:'[a]'通常用於所有三種已知有限,已知無限和可能無限的列表,這是我持久性寵物之一。 >:[ –