
On Sat, Apr 16, 2011 at 8:05 PM, Edward Z. Yang
I suspect you want something a little more clever. In particular, because replicateM uses sequence under the hood, which is quite strict: it requires all of the IO actions to be evaluated before evaluation continues, so you end up with a big list built up in memory before it gets summed by 'sum'. I suspect if you run it manually with something like this you might do better:
let loop 0 s = return s loop n s = do x <- c'gsl_rng_uniform rng loop (n-1) (s+x) print =<< loop n 0
With an actually pure function, you can do it more nicely, but it's a bit more fragile that way. Lazy IO would be another mechanism, although some people regard that to be a bit evil (and you'd still need to write the lazy IO equivalent of sequence).
You may use an iteratee for the same purpose. Using John Millikin's enumerator package, you can separate the function that calls the C code in an enumerator import qualified Data.Enumerator as E enumerator :: Integer -> E.Enumerator Double IO b enumerator n = E.replicateM n c'gsl_mg_uniform and the code that sums the values in an iteratee iteratee :: Monad m => E.Iteratee m Double iteratee = E.foldl' (+) 0 Calling them is as simple as E.run $ enumerator n $$ iteratee but note that you can also test your iteratee (which may be more complex than just summing) on any monad, including Identity. But unfortunately I don't think GHC (at least 6.12) can transform this code into something tidy as Edward's code. =( Cheers! =) -- Felipe.