packages feed

lfudacaching-0.1.0.0: app/Main.hs

module Main (main) where

import Data.LfudaCache
import Data.Foldable (foldl')
import Prelude hiding (lookup)


main :: IO ()
main = do
  putStrLn "=== LFUDA Cache Demo ==="
  putStrLn ""

  -- Create a small cache to demonstrate eviction behavior
  let cache :: LfudaCache String Int
      cache = newLFUDA 3
  putStrLn $ "Created LFUDA cache with capacity 3"
  putStrLn ""

  -- Insert some entries
  let c1 = insert "alice" (100 :: Int) cache
  let c2 = insert "bob"   200 c1
  let c3 = insert "carol" 300 c2
  putStrLn $ "Inserted alice=100, bob=200, carol=300"
  putStrLn $ "Size: " ++ show (size c3)
  putStrLn $ "Keys: " ++ show (keys c3)
  putStrLn ""

  -- Lookup bumps frequency
  putStrLn "Looking up 'alice' 3 times (bumps frequency)..."
  let c4 = foldl' (\c _ -> case lookup "alice" c of
                      Just (_, c') -> c'
                      Nothing -> c
                   ) c3 [1..3 :: Int]

  -- Insert a 4th entry - should evict lowest frequency entry
  -- Use insertView to see what was evicted
  let (evicted, c5) = insertView "dave" 400 c4
  putStrLn $ "Inserted dave=400, eviction occurred: " ++ show (evicted /= Nothing)
  case evicted of
    Just (k, v) -> putStrLn $ "Evicted: " ++ show k ++ "=" ++ show v
    Nothing     -> pure ()
  putStrLn $ "Keys after eviction: " ++ show (keys c5)
  putStrLn $ "alice still in cache: " ++ show (contains "alice" c5)
  putStrLn ""

  -- Demonstrate peek vs lookup
  putStrLn "--- Peek vs Lookup ---"
  case peek "alice" c5 of
    Just v  -> putStrLn $ "peek alice = " ++ show v ++ " (no frequency update)"
    Nothing -> putStrLn "alice not found"

  case lookup "alice" c5 of
    Just (v, _) -> putStrLn $ "lookup alice = " ++ show v ++ " (frequency updated)"
    Nothing     -> putStrLn "alice not found"
  putStrLn ""

  -- Demonstrate insertView
  putStrLn "--- InsertView ---"
  let (evictedEntry, c6) = insertView "eve" 500 c5
  case evictedEntry of
    Just (k, v) -> putStrLn $ "Evicted: " ++ show k ++ "=" ++ show v
    Nothing     -> putStrLn "No eviction"
  putStrLn $ "Keys: " ++ show (keys c6)
  putStrLn ""

  -- Compare policies
  putStrLn "=== Policy Comparison ==="
  putStrLn ""
  comparePolicies

comparePolicies :: IO ()
comparePolicies = do
  let capacity :: Int
      capacity = 3
      items :: [(String, Int)]
      items = [("a", 1), ("b", 2), ("c", 3), ("d", 4), ("e", 5)]

  -- For each policy, insert items and show what survives
  let policies :: [(CachePolicy, String)]
      policies = [(LFUDA, "LFUDA"), (GDSF, "GDSF"), (LFU, "LFU")]

  mapM_ (\(policy, name) -> do
    let cache0 :: LfudaCache String Int
        cache0 = newCache capacity policy
        -- Insert first 3
        cache1 = foldl' (\c (k, v) -> insert k v c) cache0 (take 3 items)
    -- Bump frequency of "a"
    let cache2 = foldl' (\c _ -> case lookup "a" c of
                            Just (_, c') -> c'
                            Nothing -> c
                         ) cache1 [1..2 :: Int]
    -- Insert remaining 2
    let cache3 = foldl' (\c (k, v) -> insert k v c) cache2 (drop 3 items)

    putStrLn $ name ++ ":"
    putStrLn $ "  Surviving keys: " ++ show (keys cache3)
    putStrLn $ "  Age: " ++ show (age cache3)
    ) policies