api-tools-0.9.0.0: src/Data/API/Utils.hs
module Data.API.Utils
( simpleParseVersion
, (?!)
, (?!?)
-- * Utils for merging and diffing maps
, MergeResult(..)
, mergeMaps
, diffMaps
, matchMaps
) where
import Data.Map ( Map )
import qualified Data.Map as Map
import Data.Version
import qualified Text.ParserCombinators.ReadP as ReadP
simpleParseVersion :: String -> Maybe Version
simpleParseVersion s = case filter (null . snd) (ReadP.readP_to_S parseVersion s) of
[(v,_)] -> Just v
_ -> Nothing
-- | The \"oh noes!\" operator.
--
(?!) :: Maybe a -> e -> Either e a
Nothing ?! e = Left e
Just x ?! _ = Right x
(?!?) :: Either e a -> (e -> e') -> Either e' a
Left e ?!? f = Left (f e)
Right x ?!? _ = Right x
-------------------------------------
-- Utils for merging and diffing maps
--
data MergeResult a b = OnlyInLeft a | InBoth a b | OnlyInRight b
deriving (Eq, Show)
mergeMaps :: Ord k => Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps m1 m2 = Map.unionWith (\(OnlyInLeft a) (OnlyInRight b) -> InBoth a b)
(fmap OnlyInLeft m1) (fmap OnlyInRight m2)
diffMaps :: (Eq a, Ord k) => Map k a -> Map k a -> Map k (MergeResult a a)
diffMaps m1 m2 = Map.filter different $ mergeMaps m1 m2
where
different (InBoth a b) = a /= b
different _ = True
-- | Attempts to match the keys of the maps to produce a map from keys
-- to pairs.
matchMaps :: Ord k => Map k a -> Map k b -> Either (k, Either a b) (Map k (a, b))
matchMaps m1 m2 = Map.traverseWithKey win $ mergeMaps m1 m2
where
win _ (InBoth x y) = return (x, y)
win k (OnlyInLeft x) = Left (k, Left x)
win k (OnlyInRight x) = Left (k, Right x)