[Haskell-beginners] Calling a foreign function: superlinear comlexity
Felipe Almeida Lessa
felipe.lessa at gmail.com
Sun Apr 17 01:47:48 CEST 2011
On Sat, Apr 16, 2011 at 8:05 PM, Edward Z. Yang <ezyang at mit.edu> wrote:
> 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.
More information about the Beginners
mailing list