[Haskell-cafe] Troubles understanding memoization in SOE
Paul L
ninegua at gmail.com
Mon Sep 24 17:43:07 EDT 2007
If you read the memo1 function carefully you'll notice that the cache
always contains just one pair. It's coincident that just memo-ing one
last function application is enough for the SOE examples. You could,
for example, make it memo-ing last two or more results.
The reason for this memoization hack in SOE is complicated.
Recursively defined signals using switch will have time/space leak if
not for the memoization, which itself is complicated that one can't
simply use a shared list to achieve it. Hence the hack using unsafe
operation.
The loss of sharing of function application results is fundementally
rooted in the call-by-need evaluation strategy, which, unlike optimal
evaluation, doesn't share the reduction of "virtual redex"es.
There are a number of ways to get around this problem, and memoization
is one of them. By re-structuring the code, or choosing different data
structures, one could also avoid such problems. The evolution of FRP
into Yampa/Arrow is a good example, where no memoization is needed.
We recently wrote a paper about the leak problem. The draft is at
http://www.cs.yale.edu/~hl293/download/leak.pdf. Comments are welcome!
Regards
Paul Liu
On 9/24/07, bf3 at telenet.be <bf3 at telenet.be> wrote:
> I don't know, "me newbie, you expert" ;-) I just pasted the code from the
> SOE website.
>
> But note that it is using pointers to the infinite lists to avoid comparing
> them by content (which wouldn't work, since they're infinite), so it has to
> use unsafePerformIO no?
>
> inCache :: a -> [(a,b)] -> Maybe b
> x `inCache` [] = Nothing
> x `inCache` ((x',y'):xys) =
> if unsafePtrEq x x' then Just y' else x `inCache` xys
>
> But what I don't understand is that I guess this code memoizes the full
> list, while it should just memoize the tail that is still reachable through
> the garbage collector? Or maybe that is what a "pointer to list" is? Some
> kind of weak pointer / stable name that points to the tail of the list that
> is still needed for evaluation? Hard stuff for a newbie, but I got to
> understand how it works, so I can fit one more piece of the growing Haskell
> puzzle :)
>
> Peter
>
> -----Original Message-----
> From: Henning Thielemann [mailto:lemming at henning-thielemann.de]
> Sent: Monday, September 24, 2007 1:44 PM
> To: Peter Verswyvelen
> Cc: Haskell-Cafe
> Subject: Re: [Haskell-cafe] Troubles understanding memoization in SOE
>
>
> On Sat, 22 Sep 2007, Peter Verswyvelen wrote:
>
> > Hi,
> >
> > in SOE, the following memoization function is implemented:
> >
> > memo1 :: (a->b) -> (a->b)
> > memo1 f = unsafePerformIO $ do
> > cache <- newIORef []
> > return $ \x -> unsafePerformIO $ do
> > vals <- readIORef cache
> > case x `inCache` vals of
> > Nothing -> do let y = f x
> > writeIORef cache [(x,y)] -- ((x,y) : --
> > if null vals then [] else [head vals])
> > return y
> > Just y -> do return y
>
> Hm, why the unsafePerformIO hacks? It should be possible without:
> http://www.haskell.org/haskellwiki/Memoization
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
More information about the Haskell-Cafe
mailing list