content: {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TemplateHaskell #-}
  {-# LANGUAGE DeriveDataTypeable #-}
  
  import Data.Acid
  import Data.Typeable
  import Data.SafeCopy
  import Control.Monad.Reader (ask)
  
  import qualified Data.Map as Map
  import qualified Control.Monad.State as S
  
  type Key = String
  type Value = String
  
  data Database = Database !(Map.Map Key Value)
      deriving (Show, Ord, Eq, Typeable)
  
  $(deriveSafeCopy 0 'base ''Database)
  
  insertKey :: Key -> Value -> Update Database ()
  insertKey key value
      = do Database m <- S.get
           S.put (Database (Map.insert key value m))
  
  lookupKey :: Key -> Query Database (Maybe Value)
  lookupKey key
      = do Database m <- ask
           return (Map.lookup key m)
  
  deleteKey :: Key -> Update Database ()
  deleteKey key
      = do Database m <- S.get
           S.put (Database (Map.delete key m))
  
  allKeys :: Int -> Query Database [(Key, Value)]
  allKeys limit
      = do Database m <- ask
           return $ take limit (Map.toList m)
  
  $(makeAcidic ''Database ['insertKey, 'lookupKey, 'allKeys, 'deleteKey])
  
  fixtures :: Map.Map String String
  fixtures = Map.empty
  
  test ::  Key -> Value -> IO ()
  test key val = do
      database <- openLocalStateFrom "db/" (Database fixtures)
      result <- update database (InsertKey key val)
      result <- query database (AllKeys 10)
      print result
  