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

{- |
   Module     : Data.AssocList
   Copyright  : Copyright (C) 2010 Uwe Schmidt
   License    : MIT

   Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
   Stability  : stable
   Portability: portable

   Simple key value assocciation list
   implemented as unordered list of pairs

-}

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

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 :: forall k v. Eq k => v -> k -> AssocList k v -> v
lookupDef v
d k
k   = forall a. a -> Maybe a -> a
fromMaybe v
d forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup k
k

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

lookup1         :: Eq k => k -> AssocList k [e] -> [e]
lookup1 :: forall k e. Eq k => k -> AssocList k [e] -> [e]
lookup1 k
k       = forall a. a -> Maybe a -> a
fromMaybe [] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup k
k

-- | test for existence of a key

hasEntry        :: Eq k => k -> AssocList k v -> Bool
hasEntry :: forall k v. Eq k => k -> AssocList k v -> Bool
hasEntry k
k      = forall a. Maybe a -> Bool
isJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup k
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 :: forall k v. Eq k => k -> v -> AssocList k v -> AssocList k v
addEntry k
k v
v AssocList k v
l  = ( (k
k,v
v) forall a. a -> [a] -> [a]
: ) forall a b. (a -> b) -> a -> b
$! forall k v. Eq k => k -> AssocList k v -> AssocList k v
delEntry k
k AssocList k v
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 :: forall k v. Eq k => AssocList k v -> AssocList k v -> AssocList k v
addEntries      = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall k v. Eq k => k -> v -> AssocList k v -> AssocList k v
addEntry) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse

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

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

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

delEntries      :: Eq k => [k] -> AssocList k v -> AssocList k v
delEntries :: forall k v. Eq k => [k] -> AssocList k v -> AssocList k v
delEntries      = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall k v. Eq k => k -> AssocList k v -> AssocList k v
delEntry

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