    -- |
    -- simple key value assocciation list
    -- implemented as unordered list of pairs
    --
    -- Version : $Id: AssocList.hs,v 1.2 2005/05/27 13:15:23 hxml Exp $

    module Data.AssocList
        ( module Data.AssocList
        )
    where

    import Data.Maybe

    type AssocList k v = [(k, v)]

    -- lookup       = lookup from Prelude

    -- | lookup with default value

    lookupDef       :: Eq k => v -> k -> AssocList k v -> v
    lookupDef d k   = fromMaybe d . lookup k

    -- | lookup with empty list (empty string) as default value

    lookup1         :: Eq k => k -> AssocList k [e] -> [e]
    lookup1 k       = fromMaybe [] . lookup k

    -- | test for existence of a key

    hasEntry        :: Eq k => k -> AssocList k v -> Bool
    hasEntry k      = isJust . lookup k

    -- | add an entry, remove an existing entry before adding the new one at the top of the list, addEntry is strict

    addEntry        :: Eq k => k -> v -> AssocList k v -> AssocList k v
    addEntry k v l  = ( (k,v) : ) $! delEntry k l

     -- let l' = delEntry k l in seq l' ((k, v) : l')

    -- | add a whole list of entries with 'addEntry'

    addEntries      :: Eq k => AssocList k v -> AssocList k v -> AssocList k v
    addEntries      = foldr (.) id . map (uncurry addEntry) . reverse

    -- | delete an entry, delEntry is strict
    delEntry        :: Eq k => k -> AssocList k v -> AssocList k v
    delEntry _ []   = []
    delEntry k (x@(k1,_) : rest)
        | k == k1   = rest
        | otherwise = ( x : ) $! delEntry k rest

    -- delEntry k   = filter ((/= k) . fst)

    -- | delete a list of entries with 'delEntry'

    delEntries      :: Eq k => [k] -> AssocList k v -> AssocList k v
    delEntries      = foldl (.) id . map delEntry

    -- -----------------------------------------------------------------------------