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