ruler-0.4.0.0: src/Gam.chs
-------------------------------------------------------------------------
-- Gamma
-------------------------------------------------------------------------
%%[1 hs module(Gam)
%%]
%%[1 hs export ( Gam, emptyGam, gamIsEmpty, gamSingleton, gamMember)
%%]
%%[1 hs export (gamTryLookups, gamTryLookupsWithDefault)
%%]
%%[1 hs export (gamLookup, gamLookupMaybe, gamLookupJust, gamFindWithDefault)
%%]
%%[1 hs export (gamUnions, gamUnionsShadow, gamUnion, gamUnionShadow, gamUnionWith)
%%]
%%[1 hs export (gamDelete)
%%]
%%[1 hs export (gamInsert, gamInsertShadow)
%%]
%%[1 hs export (gamDifference, gamIntersection)
%%]
%%[1 hs export (gamToMap)
%%]
%%[1 hs export (gamAssocs, gamAssocsShadow, gamFromAssocs, gamFromAssocsWith)
%%]
%%[1 hs export (gamElems, gamElemsShadow)
%%]
%%[1 hs export (gamKeys)
%%]
%%[1 hs export (gamMap, gamMapKeys, gamMapWithKey)
%%]
%%[1 hs export (gamFilterWithKey, gamFilter)
%%]
%%[1 hs export (gamPartition)
%%]
%%[1 hs export (gamMapAccumWithKey)
%%]
%%[1 hs export (gamFold, gamFoldWithKey)
%%]
%%[1 hs export (gamCheckDups)
%%]
%%[1 hs export (ppGam, ppGam')
%%]
%%[1 hs export (dblGamLookup, tripleGamLookup)
%%]
%%[1 hs export (GamMerge(..))
%%]
%%[1 hs import (Data.Maybe)
%%]
%%[1 hs import (qualified Data.Map as Map)
%%]
%%[1 hs import (UHC.Util.Pretty)
%%]
%%[1 hs import (UHC.Util.Utils)
%%]
%%[1 hs import (Err)
%%]
%%[1 hs import (Common)
%%]
%%[1
-------------------------------------------------------------------------
-- Gam
-------------------------------------------------------------------------
type Gam k v = Map.Map k [v]
liftList :: (v -> v -> v) -> ([v] -> [v] -> [v])
liftList f = \(v1:v1s) (v2:v2s) -> [f v1 v2] ++ v1s ++ v2s
liftList2 :: (v -> v -> v) -> ([v] -> [v] -> [v])
liftList2 f = \v1s v2s -> [foldr1 f (v1s ++ v2s)]
liftAnyWithKey :: (k -> v -> w) -> (k -> [v] -> w)
liftAnyWithKey f = \k (v:_) -> f k v
liftAny :: (v -> w) -> ([v] -> w)
liftAny f = \(v:_) -> f v
liftMap :: (v -> w) -> ([v] -> [w])
liftMap = map
liftMapKey :: (k -> v -> w) -> (k -> [v] -> [w])
liftMapKey f k = map (f k)
liftMapAccumKey :: (a -> k -> b -> (a, c)) -> (a -> k -> [b] -> (a, [c]))
liftMapAccumKey f a k bs
= l a bs
where l a [] = (a,[])
l a (b:bs) = (a3,c:cs)
where (a2,c ) = f a k b
(a3,cs) = l a2 bs
liftFoldKey :: (k -> v -> a -> a) -> (k -> [v] -> a -> a)
liftFoldKey f k vs a
= l a vs
where l a [] = a
l a (v:vs) = l (f k v a) vs
liftFold :: (v -> a -> a) -> ([v] -> a -> a)
liftFold f vs a
= l a vs
where l a [] = a
l a (v:vs) = l (f v a) vs
liftAssocs :: [(k,v)] -> [(k,[v])]
liftAssocs = map (\(k,v) -> (k,[v]))
gamSingleton :: k -> v -> Gam k v
gamSingleton k v = Map.singleton k [v]
gamLookup :: Ord k => k -> Gam k v -> Maybe v
gamLookup k = fmap head . Map.lookup k
gamLookupMaybe :: Ord k => w -> (v -> w) -> k -> Gam k v -> w
gamLookupMaybe n j k = maybe n j . gamLookup k
gamLookupJust :: Ord k => k -> Gam k v -> v
gamLookupJust = gamLookupMaybe (panic "gamLookupJust") id
gamAssocsShadow :: Gam k v -> [(k,v)]
gamAssocsShadow = Map.assocs . Map.map head
gamAssocs' :: Gam k v -> [[(k,v)]]
gamAssocs' g = [ zip (repeat k) vs | (k,vs) <- Map.assocs g ]
gamAssocs :: Gam k v -> [(k,v)]
gamAssocs = concat . gamAssocs'
gamElemsShadow :: Gam k v -> [v]
gamElemsShadow = map head . Map.elems
gamElems :: Gam k v -> [v]
gamElems = concat . Map.elems
gamFromAssocs :: Ord k => [(k,v)] -> Gam k v
gamFromAssocs = Map.fromListWith (++) . liftAssocs
gamFromAssocsWith :: Ord k => (v -> v -> v) -> [(k,v)] -> Gam k v
gamFromAssocsWith f = Map.fromListWith (liftList f) . liftAssocs
gamToMap :: Gam k v -> Map.Map k v
gamToMap = Map.map head
gamUnionWith :: Ord k => (v -> v -> v) -> Gam k v -> Gam k v -> Gam k v
gamUnionWith f = Map.unionWith (liftList f)
gamUnion :: Ord k => Gam k v -> Gam k v -> Gam k v
gamUnion = Map.unionWith (++)
gamUnionShadow :: Ord k => Gam k v -> Gam k v -> Gam k v
gamUnionShadow = Map.unionWith const
gamUnions :: Ord k => [Gam k v] -> Gam k v
gamUnions = Map.unionsWith (++)
gamUnionsShadow :: Ord k => [Gam k v] -> Gam k v
gamUnionsShadow = Map.unionsWith const
gamInsert :: Ord k => k -> v -> Gam k v -> Gam k v
gamInsert k v = Map.insertWith (++) k [v]
gamInsertShadow :: Ord k => k -> v -> Gam k v -> Gam k v
gamInsertShadow k v = Map.insertWith const k [v]
gamFilterWithKey :: Ord k => (k -> v -> Bool) -> Gam k v -> Gam k v
gamFilterWithKey f = Map.filterWithKey (liftAnyWithKey f)
gamFilter :: Ord k => (v -> Bool) -> Gam k v -> Gam k v
gamFilter f = Map.filter (liftAny f)
gamPartition :: Ord k => (v -> Bool) -> Gam k v -> (Gam k v,Gam k v)
gamPartition f = Map.partition (liftAny f)
gamMap :: (v -> w) -> Gam k v -> Gam k w
gamMap f = Map.map (liftMap f)
gamMapWithKey :: (k -> v -> w) -> Gam k v -> Gam k w
gamMapWithKey f = Map.mapWithKey (liftMapKey f)
gamMapAccumWithKey :: (a -> k -> b -> (a, c)) -> a -> Gam k b -> (a, Gam k c)
gamMapAccumWithKey f = Map.mapAccumWithKey (liftMapAccumKey f)
gamFoldWithKey :: (k -> v -> a -> a) -> a -> Gam k v -> a
gamFoldWithKey f = Map.foldrWithKey (liftFoldKey f)
gamFold :: (v -> a -> a) -> a -> Gam k v -> a
gamFold f = Map.fold (liftFold f)
gamKeysWithDup :: Gam k v -> [k]
gamKeysWithDup g = [ k | (k,(_:_:_)) <- Map.toList g ]
-------------------------------------------------------------------------
-- Gam v1 & v2 share
-------------------------------------------------------------------------
emptyGam :: Gam k v
emptyGam = Map.empty
gamIsEmpty :: Gam k v -> Bool
gamIsEmpty = Map.null
gamMember :: Ord k => k -> Gam k v -> Bool
gamMember = Map.member
gamFindWithDefault :: Ord k => v -> k -> Gam k v -> v
gamFindWithDefault v k = maybe v id . gamLookup k
gamKeys :: Gam k v -> [k]
gamKeys = Map.keys
gamDelete :: Ord k => k -> Gam k v -> Gam k v
gamDelete = Map.delete
gamDifference :: Ord k => Gam k v -> Gam k w -> Gam k v
gamDifference = Map.difference
gamIntersection :: Ord k => Gam k v -> Gam k w -> Gam k v
gamIntersection = Map.intersection
gamMapKeys :: Ord j => (k -> j) -> Gam k v -> Gam j v
gamMapKeys = Map.mapKeys
-------------------------------------------------------------------------
-- Duplicate key detection
-------------------------------------------------------------------------
gamCheckDups :: PP k => SPos -> String -> String -> Gam k v -> [Err]
gamCheckDups p cx knd g
= if null d then [] else [Err_Dups p cx knd (map pp d)]
where d = gamKeysWithDup g
-------------------------------------------------------------------------
-- Merging
-------------------------------------------------------------------------
class GamMerge g where
gamMerge :: g -> g -> g
instance (Ord k,GamMerge v) => GamMerge (Gam k v) where
gamMerge = Map.unionWith (liftList2 gamMerge)
-------------------------------------------------------------------------
-- Pretty printing
-------------------------------------------------------------------------
{-
ppGam :: (PP k, PP v) => Gam k v -> PP_Doc
ppGam = ppListSepV "[" "]" "," . map (\(k,v) -> pp k >#< ":->" >#< pp v) . gamAssocs
-}
ppGam :: (PP k, PP v) => Gam k v -> PP_Doc
ppGam
= ppl . map (ppl . map (\(k,v) -> pp k >#< ":->" >#< pp v)) . gamAssocs'
where ppl = ppListSepV "[" "]" ","
ppGam' :: (PP k, PP v) => Gam k v -> PP_Doc
ppGam' = vlist . map (\(k,v) -> pp k >#< ":->" >#< pp v) . gamAssocs
instance (PP k,PP v) => PP (Gam k v) where
pp g = ppGam' g
-------------------------------------------------------------------------
-- Double/... lookup
-------------------------------------------------------------------------
contGamLookup :: Ord k => (i1 -> Gam k i2) -> (i2 -> r) -> k -> i1 -> Maybe r
contGamLookup g2Of mk n2 = fmap mk . gamLookup n2 . g2Of
dblGamLookup :: Ord k => (i1 -> Gam k i2) -> k -> k -> Gam k i1 -> Maybe (i1,i2)
dblGamLookup g2Of n1 n2 g
= case gamLookup n1 g of
Just i1
-> contGamLookup g2Of ((,) i1) n2 i1
_ -> Nothing
tripleGamLookup :: Ord k => (i1 -> Gam k i2) -> (i2 -> Gam k i3) -> k -> k -> k -> Gam k i1 -> Maybe (i1,i2,i3)
tripleGamLookup g2Of g3Of n1 n2 n3 g
= case dblGamLookup g2Of n1 n2 g of
Just (i1,i2)
-> contGamLookup g3Of (\i3 -> (i1,i2,i3)) n3 i2
_ -> Nothing
-------------------------------------------------------------------------
-- General purpose lookup with a default key
-------------------------------------------------------------------------
gamTryLookups :: Ord k => v -> (e -> v) -> [k] -> Gam k e -> v
gamTryLookups dflt extr keys g
= case keys of
(k:ks) -> case gamLookup k g of
Just i -> extr i
Nothing -> gamTryLookups dflt extr ks g
_ -> dflt
gamTryLookupsWithDefault :: Ord k => k -> v -> (e -> v) -> [k] -> Gam k e -> v
gamTryLookupsWithDefault dfltKey dflt extr keys g
= gamTryLookups dflt extr (keys ++ [dfltKey]) g
%%]