2015-09-21 18 views
9

Tembel bir listeyi sabit alanda monadik eylemler kullanarak nasıl katlayabilirim? Çözmeyi denediğim problem büyük bir dosya topluyor, ve performans uğruna mutabiliteye ihtiyacım olduğuna inanıyorum. ST'de mutable vektörleri kullanarak çalışan bir uygulama var, ama çok fazla bellek kullanıyor. Aşağıda, denediğim şeyin bir örneği var. Ayrıca Conduit ile kısa bir süre deney yaptım, ancak bu herhangi bir gelişme sağladı.Sabit Alanda Monadic Katlama

ST Form_:

import Control.Monad (forM_) 
import Control.Monad.ST.Trans as STT 
import Control.Monad.Identity as Identity 

testST :: Int 
testST = do 
    Identity.runIdentity $ STT.runST $ do 
    a <- STT.newSTRef 0 
    forM_ [1..10000000] (\x -> do 
     a' <- STT.readSTRef a 
     STT.writeSTRef a (a' + x) 
    ) 
    STT.readSTRef a 

Boru:

import Data.Conduit (($=),(=$),($$)) 
import qualified Data.Conduit as C 
import qualified Data.Conduit.List as CL 

testCL :: IO Int 
testCL = CL.sourceList [1..10000000] $$ CL.foldM (\a x -> return (a + x)) 0 
+0

Performans ayarlama için: “STT s Identity” nin her zamanki “ST s” üzerinde bir miktar tahsisatı olacaktır; Eğer tuhaf 'STT' güçlerine ihtiyacınız yoksa, sadece 'ST' kullanmak isteyebilirsiniz. – dfeuer

+0

@dfeuer Gerçekten de onu kaldırabilirim, ancak ilk başta 'Her şeyi' gömmek zorunda kalmayı bekleyen uygulamaya koydum ve aktarıldı. Bahşiş için teşekkürler! – ryachza

cevap

15

sorun kat ile değil, ancak kat gövdeli. Bu program çok ayırır:

testST = runST $ do 
    ref <- newSTRef 0 
    forM_ [1..10000000] $ \x -> do 
     val <- readSTRef ref 
     writeSTRef ref $! val + x 
    readSTRef ref 

kodunun iki parça arasındaki fark ne kadar iyi bir ipucu:

testST = runST $ do 
    ref <- newSTRef 0 
    forM_ [1..10000000] $ \x -> do 
     val <- readSTRef ref 
     writeSTRef ref (val + x) 
    readSTRef ref 

Bu programı kimin tek fark writeSTRef hattı üzerinde, hemen hemen hiçbir şey ayırır devam ediyor: eskiden, 10000000 katmanları olan + uygulamalarıyla derin bir yuvaya bir referans oluşturuyorsunuz; ikincisi her adımda thunk düzleştirir. Bu sıradan tuzak explicitly called out in the documentation for modifySTRef şeklindedir

+0

Teşekkürler bu mükemmel çalıştı. Birkaç sıkılık ek açıklamaları ve farklı katlama yöntemlerini denedim ancak odaklamam her zaman uygulamada değil argümanlar üzerindeydi. Yazma değeri olduğu düşüncesi aklımdan hiç geçmedi. – ryachza

+0

@ryachza Gerçekten de, bir gece geç saatte, son dakika hata ayıklama seansının umutsuzluğuyla beynime yandı ... –