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
のはプレリュードからのものだけですが、いくつかの欠点があります。
1つの方法は、最初に繰り返し、後でマップすることです。
my_iter f x = map f2 $ iterate f1 x
where f1 = fst . f
f2 = snd . f
ただし、fを別々のf1関数とf2関数に分割する自然な方法がない場合、これは見苦しく見える可能性があります。(考案されたフィボナッチの場合、これは簡単ですが、生成された値がシードの「独立した」関数ではないため、分割するのがそれほど簡単ではない場合があります)
もう1つの方法は、「出力」値をシードと一緒にタプルし、別のステップを使用してそれらを分離することです(ソート用の「シュワルツ変換」のようなものです)。
my_iter f x = map snd . tail $ iterate (f.fst) (x, undefined)
しかし、シード((f.fst)ビット)に到達するために生成された値を無視し、最初のダミーの生成された値に「未定義」の値を追加する必要があるため、これは奇妙に思えます。