Revert a CAF?

Simon Marlow marlowsd at gmail.com
Thu Dec 8 10:26:33 CET 2011


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



More information about the Glasgow-haskell-users mailing list