home *** CD-ROM | disk | FTP | other *** search
- {-----------------------------------------------------------------------------
-
- A LIBRARY OF MEMOIZATION COMBINATORS
-
- 15th September 1999
-
- Byron Cook
- OGI
-
- This Hugs module implements several flavors of memoization functions,
- as described in Haskell Workshop 1997.
- -----------------------------------------------------------------------------}
-
- module Memo(
- memo,
- memoN,
- memoFix,
- memoFixN,
- cache,
- cacheN,
- cacheFix,
- cacheFixN
- ) where
-
- import ST
- -- import IOExts (unsafePtrEq, trace)
-
- memo :: (a -> b) -> (a -> b)
- memoN :: Int -> (a -> b) -> (a -> b)
- memoFix :: ((a -> b) -> (a -> b)) -> (a -> b)
- memoFixN :: Int -> ((a -> b) -> (a -> b)) -> (a -> b)
- cache :: (a -> b) -> (a -> b)
- cacheN :: Int -> (a -> b) -> (a -> b)
- cacheFix :: ((a -> b) -> (a -> b)) -> (a -> b)
- cacheFixN :: Int -> ((a -> b) -> (a -> b)) -> (a -> b)
-
- ----------------------------------------------------------------
- -- Memoization Functions (memo-tables are hash-tables)
- ----------------------------------------------------------------
- memo = memoN defaultSize
- memoN = mkMemo eql hash
-
- memoFix = memoFixN defaultSize
- memoFixN n f = let g = f h
- h = memoN n g
- in g
-
- ----------------------------------------------------------------
- -- Caching Functions (memo-tables are caches)
- ----------------------------------------------------------------
- cache = cacheN defaultSize
- cacheN = mkCache eql hash
- cacheFix = cacheFixN defaultSize
- cacheFixN n f = let g = f h
- h = cacheN n g
- in g
-
- ----------------------------------------------------------------
- -- Type synonyms
- ----------------------------------------------------------------
- type TaintedEq a = a -> a -> ST Mem Bool
- type HashTable a b = STArray Mem Int [(a,b)]
- type Cache a b = STArray Mem Int (Maybe (a,b))
- type HashSize = Int
- type HashFunc a = a -> ST Mem Int
- type Mem = ()
-
-
- ----------------------------------------------------------------
- -- Foundation functions
- ----------------------------------------------------------------
- defaultSize :: HashSize
- defaultSize = 40
-
- memoize :: ST Mem t -> (t -> a -> b -> ST Mem b) ->
- (a -> b) -> a -> b
- memoize new access f = {-trace "memoize" $-} unsafeST $ do
- t <- new
- return (\x -> unsafeST $ access t x (f x))
-
-
- mkMemo :: TaintedEq a -> HashFunc a -> Int -> (a -> c) -> (a -> c)
- mkCache :: TaintedEq a -> HashFunc a -> Int -> (a -> c) -> (a -> c)
-
- mkCache e h sz = memoize (newCache sz) (accessCache e h sz)
- mkMemo e h sz = memoize (newHash sz) (accessHash e h sz)
-
-
- ----------------------------------------------------------------
- -- Hash and Cache Tables
- ----------------------------------------------------------------
- accessHash :: TaintedEq a ->
- HashFunc a ->
- Int ->
- HashTable a b ->
- a -> b -> ST Mem b
-
- accessHash equal h sz table x v = do
- hv' <- h x
- let hv = hv' `mod` sz
- l <- readSTArray table hv
- find l l hv
- where find l [] hv = {-trace "miss " $-} do
- u <- writeSTArray table hv ((x,v):l)
- case u of {() -> return v}
- find l ((x',v'):xs) hv = do
- a <- equal x x'
- if a then {-trace "hit "-} (return $ v')
- else find l xs hv
-
- newHash :: Int -> ST Mem (HashTable a b)
- newHash n = newSTArray (0,n) []
-
-
- accessCache :: TaintedEq a ->
- HashFunc a ->
- Int ->
- Cache a b ->
- a -> b -> ST Mem b
-
- accessCache equal h sz table x v = do
- hv' <- h x
- let hv = hv' `mod` sz
- l <- readSTArray table hv
- case l of
- Nothing -> do u <- writeSTArray table hv (Just (x,v))
- case u of {() -> return v}
- Just (x',y) -> do e <- equal x' x
- if e then return y
- else do u <- writeSTArray table hv (Just (x,v))
- case u of {() -> return v}
-
- newCache :: Int -> ST Mem (Cache a b)
- newCache n = newSTArray (0,n) Nothing
-
- ------------------------------------------------------------------
- -- These functions are bad --- dont pay attention to them
- primitive primUnsafeCoerce "primUnsafeCoerce" :: a -> b
-
- unsafeST :: ST s a -> a
- unsafeST m = fst (reifyST m ())
-
- reifyST :: ST s a -> (b -> (a,b))
- reifyST = primUnsafeCoerce
-
- -- lisp style eql --- as described in "Lazy-memo functions"
- primitive eql "STEql" :: a -> a -> ST Mem Bool
- -- a `eql` b = return (a `unsafePtrEq` b)
-
- -- hash based on addresses (or values if the arg is a base type)
- primitive hash "STHash" :: a -> ST Mem Int
-
- ------------------------------------------------------------------
-