Hi, 
On 29.01.2012, at 23:30, wren ng thornton wrote:

> On 1/29/12 5:48 AM, Roman Cheplyaka wrote:
>> * wren ng thornton<w...@freegeek.org>  [2012-01-28 23:06:08-0500]
>> 
>> Why not to make it more pure? That is, return a lazy list of Ints (but
>> not a CAF), which user can throw away by the usual GC means?
>> 
>> The functions from the other modules that use primes would have to be
>> put in a Reader monad. That would make it a little bit more awkward to
>> use, but personally I'd prefer that over memory leaks.
> 
> I'd also prefer a more pure solution, but I don't think that the Reader monad 
> is the right tool here. I played around with that approach, but it requires 
> extremely invasive changes to client code, obfuscating what should be simple 
> mathematical formulae. And, it's too fragile, exposing the implementation in 
> a way that breaks client code should I change a non-prime-using algorithm to 
> a prime-using one, or vice versa. The fragility could be partially avoided by 
> providing both prime-using and non-prime-using algorithms, but then that 
> forces users to decide which one they want--- and if their only concern is 
> performance, then they'd have to go through the code-breaking refactoring 
> anyways, just to determine which is faster for their application.
> 
> One alternative I'm exploring is, rather than (only) making the primes not a 
> CAF, instead make the prime-using functions non-CAFs as well. That is, 
> provide a makePrimeUsingFunctions function which returns a record/tuple of 
> all the functions, sharing a stream of primes. This way, after allocating the 
> functions, they can be used purely just as in the current model; and when the 
> client wants the primes to be GCed, they can drop their references to the 
> allocated functions which use those primes (allocating new functions later, 
> if necessary).

A slight variation on that approach is to use implicit parameters to 
parameterize your functions by the primes. Something allong the following lines:

> {-# LANGUAGE ImplicitParams, Rank2Types #-}
>  
>  
> data PrimeTable                 -- abstract
>  
> withPrimes :: ((?primes :: PrimeTable) => a) -> a
> withPrimes e = e
>   where
>     ?primes = ...
>  
>  
> factorial :: (?primes :: PrimeTable) => Integer -> Integer
> factorial = ...
>  
> example = withPrimes $ ... factorial n ….

This has the advantage that the user doesn't have to bring all the elemnts of 
your tuple/record into scope. 
And you can have two modules with an almost identical content, one uses the 
implicit primes argument and the other uses a global CAF for its primes. A user 
would only have to change his type signatures and strategically add/remove a 
call to withPrimes when switching.  

Cheers,
  Jean



_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to