-- | Tries to avoid executing this computation in the future by storing it in
--   the cache.
cached :: Monad m => Cache m k a -> k -> m a -> m a
cached c k computeSlowly = do
    r <- readCache c k
    case r of
      Just x -> return x
      Nothing -> do
        x <- computeSlowly
        _ <- writeCache c k x
        return x


-- implementations


-- | A dummy cache which never caches anything.
--
-- Semantically equivalent to `finiteCache 0 $ assocCache`, except for the `m`.
--
-- >>> withNullCache testC
-- one
-- two
-- one
-- two
-- testing
-- testing
-- [3,3,3,3,7,7]
cached :: Monad m => Cache m k a -> k -> m a -> m a
cached c k computeSlowly = do
    r <- readCache c k
    case r of
      Just x -> return x
      Nothing -> do
        x <- computeSlowly
        _ <- writeCache c k x
        return x


-- implementations


-- | A dummy cache which never caches anything.
--
-- Semantically equivalent to `finiteCache 0 $ assocCache`, except for the `m`.
--
-- >>> withNullCache testC
-- one
-- two
-- one
-- two
-- testing
-- testing
-- [3,3,3,3,7,7]
cached c k computeSlowly = do
    r <- readCache c k
    case r of
      Just x -> return x
      Nothing -> do
        x <- computeSlowly
        _ <- writeCache c k x
        return x


-- implementations


-- | A dummy cache which never caches anything.
--
-- Semantically equivalent to `finiteCache 0 $ assocCache`, except for the `m`.
--
-- >>> withNullCache testC
-- one
-- two
-- one
-- two
-- testing
-- testing
-- [3,3,3,3,7,7]