module Cache where import System.IO.Unsafe import Data.IORef import qualified Data.Map as M type Cache k a = IORef (M.Map k a) type CacheOnce k a = IORef (Maybe (k, a)) initCache :: IO a -> a initCache = unsafePerformIO newCache :: (Eq k, Ord k) => IO (Cache k a) newCache = newIORef (M.empty) newCacheOnce :: Eq k => IO (CacheOnce k a) newCacheOnce = newIORef Nothing cacheOnce :: Eq k => CacheOnce k a -> (k -> IO a) -> k -> IO a cacheOnce ref f key = do m <- readIORef ref case m of Just (k, v) | k == key -> return v _ -> do v <- f key writeIORef ref (Just (key, v)) return v cache :: (Eq k, Ord k) => Cache k a -> (k -> IO a) -> k -> IO a cache ref f key = do m <- readIORef ref case M.lookup key m of Just v -> return v _ -> do v <- f key modifyIORef ref (M.insert key v) return v