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

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

-- | delete an entry, delEntry is strict
delEntry        :: Eq k => k -> AssocList k v -> AssocList k v
delEntry :: k -> AssocList k v -> AssocList k v
delEntry k
_ []   = []
delEntry k
k (x :: (k, v)
x@(k
k1,v
_) : AssocList k v
rest)
    | k
k k -> k -> Bool
forall a. Eq a => a -> a -> Bool
== k
k1   = AssocList k v
rest
    | Bool
otherwise = ( (k, v)
x (k, v) -> AssocList k v -> AssocList k v
forall a. a -> [a] -> [a]
: ) (AssocList k v -> AssocList k v) -> AssocList k v -> AssocList k v
forall a b. (a -> b) -> a -> b
$! k -> AssocList k v -> AssocList k v
forall k v. Eq k => k -> AssocList k v -> AssocList k v
delEntry k
k AssocList 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 :: [k] -> AssocList k v -> AssocList k v
delEntries      = ((AssocList k v -> AssocList k v)
 -> (AssocList k v -> AssocList k v)
 -> AssocList k v
 -> AssocList k v)
-> (AssocList k v -> AssocList k v)
-> [AssocList k v -> AssocList k v]
-> AssocList k v
-> AssocList k v
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (AssocList k v -> AssocList k v)
-> (AssocList k v -> AssocList k v)
-> AssocList k v
-> AssocList k v
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) AssocList k v -> AssocList k v
forall a. a -> a
id ([AssocList k v -> AssocList k v]
 -> AssocList k v -> AssocList k v)
-> ([k] -> [AssocList k v -> AssocList k v])
-> [k]
-> AssocList k v
-> AssocList k v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (k -> AssocList k v -> AssocList k v)
-> [k] -> [AssocList k v -> AssocList k v]
forall a b. (a -> b) -> [a] -> [b]
map k -> AssocList k v -> AssocList k v
forall k v. Eq k => k -> AssocList k v -> AssocList k v
delEntry

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