{-+ A class for finite maps that allows different implementations to impose different constraints (e.g. Eq or Ord) on the domain type. -} module FiniteMaps2 where class FiniteMap fm d | fm->d where empty :: r -> fm r lookup :: fm r -> d -> r update :: d -> r -> fm r -> fm r {-+ Example 1: functions as finite maps: -} instance Eq d => FiniteMap ((->) d) d where empty r = const r lookup = id update d r fm d' = if d'==d then r else fm d' {-+ Example 2: binary search trees as finite maps: -} data Tree a = Tip | Node a (Tree a) (Tree a) data FM d r = FM r (Tree (d,r)) instance Ord d => FiniteMap (FM d) d where empty r = FM r Tip lookup (FM rdefault t) d = look t where look Tip = rdefault look (Node (d',r') l r) = case compare d d' of EQ -> r' LT -> look l GT -> look r update d r (FM rdefault t) = FM rdefault (upd t) where upd Tip = Node (d,r) Tip Tip upd (Node n@(d',r') lt rt) = case compare d d' of EQ -> Node (d,r) lt rt LT -> Node n (upd lt) rt GT -> Node n lt (upd rt)