We first had some code like this:
(: test3 :fun (IO :unit)()
(:do
(:= input getContents)
(:= db (cascade-substitutions 1
(:rpipe input lines (map words)
(map create-line))))
(:= db (cascade-substitutions 2 db))
(:= db (cascade-substitutions 3 db))
(return :nothing)
))
or in Haskell:
test3 = (do{
input<-getContents;
db<-(cascade_substitutions 1
((map create_line)((map words)(lines(input)))));
db<-(cascade_substitutions 2 db);
db<-(cascade_substitutions 3 db);
(return ());
});
cascade-substitutions runs in the IO monad and produces output, as well as updates the db.
However, cut-and-paste growing the code results in the compiler (ghc 6.4) quickly running out of memory after about 1000 repetitions of the cascade-substitutions line.
After manually rewriting the do-notation we get
(>>=
(>>=
(>>=
(>>= getContents
(:lambda f1 ((input))
(cascade-substitutions 1
(create-many-lines input))))
(:lambda f2 ((db))
(cascade-substitutions 2 db)))
(:lambda f3 ((db))
(cascade-substitutions 3 db)))
(:lambda finish ((_)) (return :nothing)))
or in Haskell:
((>>=) ((>>=) ((>>=) ((>>=) getContents (\ (input) -> (cascade_substitutions 1 (create_many_lines input)))) (\ (db) -> (cascade_substitutions 2 db))) (\ (db) -> (cascade_substitutions 3 db))) (\ (_) -> (return ())))
We note that >>= is left-associative. We can put the inner loop in a list.
(:mlist (:lambda f2 ((db)) (cascade-substitutions 2 db)) (:lambda f3 ((db)) (cascade-substitutions 3 db)))
We can then generate that list with an map that generates a list of lambda functions, and (foldl >>=) them.
(>>=(foldl >>= (>>= getContents
(:lambda f1 ((input))
(cascade-substitutions 1
(create-many-lines input))))
(map
(:lambda create-f ((n))
(:lambda f ((db))
(cascade-substitutions n db)))
(enumFromTo 2 10000))
)
(:lambda finish ((_)) (return :nothing)))
or in Haskell:
((>>=) (foldl (>>=) ((>>=) getContents (\ (input) -> (cascade_substitutions 1 (create_many_lines input)))) (map (\ (n) -> (\ (db) -> (cascade_substitutions n db))) (enumFromTo 2 10000))) ((_) -> (return ())))
On one hand, I'm surprised there isn't already a "foldl bind", however this has a problem: If (enumFromTo 2 10000) is replaced with (enumFrom 2), i.e., the infinite list [2..], then the program runs out of memory during execution before producing any output. Let's try foldM.
(: test5 :fun (IO :unit) ()
(:do
(:= input getContents)
(:= _ (foldM (flip cascade-substitutions)
(create-many-lines input)
(enumFrom 1 )))
(return :nothing)
))
or in Haskell:
test5 = (do{
input<-getContents;
_<-(foldM (flip cascade_substitutions)
(create_many_lines input) (enumFrom 1));
(return ());
})
This one runs well without running out of memory. foldM is the answer.
Additional keywords: sequence, state, foldr, sequence_
No comments :
Post a Comment