%-------------------------------=  --------------------------------------------
\subsection{Finite maps}
%-------------------------------=  --------------------------------------------

%if codeOnly || showModuleHeader

> module FiniteMap		(  FiniteMap, empty, fromList, add, lookup,  (!))
> where
> import Prelude hiding		(  lookup  )
> import Maybe

%endif

> type FiniteMap key val	=  Trie key val
>
> data Trie key val		=  Leaf [key] val
>				|  Node [(key, Trie key val)] (Maybe val)

The value associated with the empty sequence is contained in the |Maybe b|
part. \NB |Node [('a', empty)] Nothing| is not legal.

> empty				:: Trie key val
> empty				=  Node [] Nothing
>
> fromList			:: (Ord key) => [([key], val)] -> Trie key val
> fromList			=  foldr add empty
>
> add				:: (Ord a) => ([a], b) -> Trie a b -> Trie a b
> add (x, v) t			=  insert t x v
>
> lookup			:: (Ord a) => [a] -> Trie a b -> Maybe b
> lookup x (Leaf y w)
>     | x == y			=  Just w
>     | otherwise 		=  Nothing
> lookup [] (Node ts w)  	=  w
> lookup (a : x) (Node ts w)  	=  lookupList ts
>     where
>     lookupList []		=  Nothing
>     lookupList ((b, t) : ts)	=  case compare b a of
>         LT 			-> lookupList ts
>         EQ 			-> lookup x t
>         GT 			-> Nothing

Derived functions.

> (!)				:: (Ord a) => Trie a b -> [a] -> b
> t ! k				=  fromJust (lookup k t)

Auxiliary functions.
%{
%align 41

> insert 				:: (Ord a) => Trie a b -> [a] -> b -> Trie a b
> insert (Leaf [] _) [] v		=  Leaf [] v
> insert (Leaf (b : y) w) [] v		=  Node [(b, Leaf y w)] (Just v)
> insert (Leaf [] w) (a : x) v		=  Node [(a, Leaf x v)] (Just w)
> insert (Leaf (b : y) w) (a : x) v	=  case compare b a of
>     LT 				-> Node [(b, Leaf y w), (a, Leaf x v)] Nothing
>     EQ 				-> Node [(a, insert (Leaf y w) x v)] Nothing
>     GT 				-> Node [(a, Leaf x v), (b, Leaf y w)] Nothing
> insert (Node ts w) [] v 		=  Node ts (Just v)
> insert (Node ts w) (a : x) v 		=  Node (insList ts) w
>     where
>     insList []			=  [(a,Leaf x v)]
>     insList ((b, t) : ts)		=  case compare b a of
>         LT 				-> (b, t) : insList ts
>         EQ 				-> (b, insert t x v) : ts
>         GT 				-> (a, Leaf x v) : (b, t) : ts

%}
