2012-04-12 24 views
9

Haskell'de oldukça geniş ama sonlu bir Kartezyen ürünü üretmek istiyorum, ki daha sonra yinelemem gerekiyor (bir ortalama alan modelinin bölüm fonksiyonunu düşünün). yapılacak doğal şey böyle, sequence kullanır:Haskell'de Lazy kartezyen ürün

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

Maalesef büyük n için, bu bellekte uymuyor ve en kısa sürede ben mesela length l istemek olarak yığın tükendi. Aynı şeyi tembel bir şekilde yapmaya ihtiyacım var. Ben (çalışıyor), bu gibi

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 

baz-3 Arithmetics "yeniden keşfetmeye" sona erdi ama tekerleği yeniden icat gibi hissediyor ve bu çok çok özeldir yanında. Ürünü üretmek için daha iyi tembel bir yol ne olurdu? daha fazla bellek dostu yolu dizisine kıyasla ters sırada bağlanarak elde edilir

+0

Sonuçtaki öğelerin sırasını önemsiyor musunuz? – augustss

+0

Hayır, tekrarlama olmadığı sürece. –

+0

Olmak için neye ihtiyacınız var? – dave4420

cevap

5

,

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

Daha az paylaşımı nedeniyle yavaştır, ancak hafıza senin sorunun beri, belki de senin için yeterince iyi.

+0

Serin! Neden çalıştığını daha fazla araştırmam gerekecek, ama kesinlikle öyle. 'Foo (l: ls) = olarak değiştirdim = [h: t | t <- foo2 ls, h <- l] '(her zaman bir küpe ihtiyacım olup olmadığını kim bilir) ve de işe yarıyor. Teşekkürler! –

+0

Niçin liste kavramaları listeler için ("dizisinde" kullanılır) notlandırmadan daha etkilidir? Haskell2010 raporunun her ikisinin de “concatMap” için desugar görebiliyorum. – haskelline

+2

Brence: Duncan Coutts'un bu reddit sorusunun cevabını görün: [Listedeki gardiyanlar niçin itirazda olduğundan daha hızlı kavranırlar?] (Http://www.reddit.com/r/haskell/comments/oolyt/why_are_guards_in_the_list_comprehension_faster /) – danr

İlgili konular