2012-04-12 8 views
9

ハスケルではかなり大きいが有限のデカルト積を生成したいと思っています。これを反復する必要があります(平均場モデルの分割関数を考える)。行うには自然なことは、このように、sequenceを使用しています。ハスケルのレイジーデカルト積

l = sequence $ replicate n [0,1,2] 

残念ながら、大nのために、これはメモリに収まらないと私はすぐに私は例えばlength lを求めるようヒープが不足し。私は同じことをゆっくりと行う方法が必要です。私はこのような基本-3算術演算、

nextConfig []  = [] 
nextConfig (0:xs) = 1:xs 
nextConfig (1:xs) = 2:xs 
nextConfig (2:xs) = 0:(nextConfig xs) 

ll = take (3^n) $ iterate nextConfig $ replicate n 0 

を「再発見」終わった(これは動作します)が、それは車輪の再発明のように感じ、それ以外にもあまりにも具体的です。製品を生成するためのより良い方法は何でしょうか?より多くのメモリに優しい方法は、配列と比較して逆の順序で結合することによって得られる

+0

結果の要素の順序は気になりますか? – augustss

+0

いいえ、繰返しがない限り。 –

+0

「n」はどれくらいの大きさが必要ですか? – dave4420

答えて

5

foo 0 _ = [[]] 
foo k xs = [h:t | t <- foo (k-1) xs, h <- xs] 

それは以下の共有のために遅くなりますが、メモリがあなたの問題があることから、多分それはあなたのために十分に良いことです。

+0

クール!なぜ私はそれが動作するかを調査しなければならないが、それは確かにある。私は 'foo(l:ls)= [h:t | t < - foo2 ls、h < - l] '(私は常にキューブが必要かどうかを知っています)、それも同様に機能します。ありがとう! –

+0

なぜリストの理解はリストのdo-notation( 'sequence'で使われる)よりも効率的ですか?私はHaskell2010のレポートから、両方とも 'concatMap'にdesugarであることが分かりますか? – haskelline

+2

@brence:このredditの質問に対するDuncan Couttsの答えを参照してください:[リスト記法の警備員はなぜdo記法よりも速いのですか?](http://www.reddit.com/r/haskell/comments/oolyt/why_are_guards_in_the_list_comprehension_faster /) – danr