On 07/12/11 15:16, Twan van Laarhoven wrote:
On 06/12/11 18:48, wren ng thornton wrote:
So, I have an optimization/internals question. Does the GHC API have any
hooks for being able to revert a CAF to the original expression, thus
discarding the previously computed result?

...

I could hack something together based on unsafePerformIO and top-level
IORefs, and it's clear that this is in fact a safe thing to do, but I'm
worried about the semantic issues inherent in unsafePerformIOed
top-level IORefs (e.g., the fact that their scope isn't particularly
well defined: is it per library instance? per runtime?...).
Unfortunately, for what I'm doing, it isn't really feasible to just
leave the IO type in there nor to pass around the infinite list so we
can use scoping rules to decide when to free it.

How bad is the IORef solution really? I.e. can someone more well versed
in ghc internals tell me why this wouldn't work?

type CAF a = IORef (() -> a, a)
mkCAF :: (() -> a) -> a
mkCAF f = unsafePerformIO $ newIORef (f, f ())
getCAF :: CAF a -> a
getCAF = snd . unsafeDupablePerformIO . readIORef
resetCAF :: CAF a -> IO ()
resetCAF = modifyIORef $ \(f,_) -> (f, f ())

myCAF :: CAF [Int]
myCAF = mkCAF $ \_ -> [1..1000000]
{-# NOINLINE myCAF #-}

What will happen here is that GHC will transform it to:

x = [1..1000000]
myCAF = mkCAF $ \_ -> x

and you're no better off. This will always happen with a function of type () -> a, because by definition the return value does not depend on the argument, so the contents will always be lifted out.

You could use -fno-full-laziness I suppose...

Cheers,
        Simon

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to