2012-03-18 11 views
6

シーケンスを折りたたみ、範囲に沿ったいくつかの点で中間値も知りたいとします。これは私はこのために使用したものである:この折りたたみと繰り返しのパターンは何ですか?

[a,b,c] = map fst . tail $ chain [g i, g j, g k] (zero, sequence) 

g :: Integer -> (a,b) -> (a,b) 

chain (f:fs) x = x : chain fs (f x) 
chain [] x = [x] 

機能gは、いくつかの初期値から開始し、同じ結果を生成する、(等長ijの)入力シーケンスの特定の部分を消費します次の呼び出しに供給される型。開始と同じ初期値から始まる異なる長さのためにシーケンスを数回消費することはもちろん、時間的にも空間的にも非効率的であろう。

したがって、この一連の整数(シーケンスの中間点)を折りたたみます。一方、この関数を繰り返し実行します(g)。それは何ですか?私はここに何か基本的なものを欠いていますこれは折り返しのレパートリーなどで何とか表現できますか?

EDIT:解決済み :修正の繰り返しが実際にある修飾子のリストの上に折る方法 上記単に

[a,b,c] = map fst . tail $ scanl (flip g) (zero, sequence) [i, j, k] 

面白いです。

+6

あなたは基本的にscanlを意味しますか? http://www.haskell.org/hoogle/?hoogle=scanl – Marcin

+1

@Marcinああ、はい、基本的なものです。おそらくそうだ。私を混乱させたのは、 'g'自体もシーケンスの上に折り畳まれていたということでした。私はスキャン機能が '(ゼロ、シーケンス)'と 'i'を組み合わせ、' [i、j、k] 'リストを直接スキャンすると思います...ありがとう、それを試みます! –

答えて

9

scanl試し:http://www.haskell.org/hoogle/?hoogle=scanl

scanlはfoldlのと同様であるが、左から連続低下 値のリストを返す:

scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...] 

なお

last (scanl f z xs) == foldl f z xs 
4

マルチンさんのコメント、あなたは基本的にしたい:

intermediates = scanl step zero sequence 
map (\n -> intermediates !! n) [i, j, k] 

stepgではなく、リストsequenceの単一の要素を消費gのほんの一部。

また、正解としてMarcin'sを受け入れます。

+0

シーケンスそのものは巨大です(* big *).2つの中間体と1つのfinalしか必要ありません。このすべてのことは、スペース消費を減らし、ghcにできるだけ多くのものを取り除く機会を与えることです。また、私はあなたの記事の5分前に受け入れました。 :)ありがとう! –

+0

上記を最適化してコンパイルした場合、GHCは使用しない中間結果を自動的にガベージコレクトする必要があります。したがって、一定のスペースで実行する必要があります。あなたが手で中間折り畳みをした場合よりも、それ以上の費用はかかりません。 –

+0

私は '(!! n)'は最初から数え始めなければならないので、シーケンス全体の存在を要求するという疑いがあります。しかし、私は後でそれを試してみます、ありがとう。次の値を生成するには、それぞれの前の値が必要です。もはやそれが必要ではなくても(gc)多くの活動であり、リスト自体はまだ維持されているので、すでに強制されているように各ノードの値を解放することさえできないかもしれません。正確に何が回避されているのかをステップで計算するとうまくいけば。私は確かに私のアプローチでは、スペースサイズの大幅な低下を見た。 –

関連する問題