packages feed

NMap (empty) → 0.12

raw patch · 3 files changed

+224/−0 lines, 3 filesdep +basedep +containerssetup-changed

Dependencies added: base, containers

Files

+ NMap.cabal view
@@ -0,0 +1,15 @@+name:       NMap+version:    0.12+synopsis:   A transparent nested Map structure+description: +category: Data+license: LGPL+author: Alejandro Castello+maintainer: a.castello.pas@gmail.com+cabal-version: >= 1.2+build-type: Simple++library+    hs-source-dirs:     src+    exposed-modules:    Data.NMap+    build-depends:      containers, base >= 3 && < 5
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Data/NMap.hs view
@@ -0,0 +1,207 @@+module Data.NMap (+    NMap, (.<), (.>), drawNMap, mapKeys, mapWithKey, mapWithKey0,+    traverseKeys, traverseWithKey, bitraverse, bisequence, mapKeysM, fromList, elems, +    delete, delete0, rootKeys, roots, lookup, (!), member, branch, branch0, insert, insert0         +    )where++import qualified Data.Map as M+import Data.Bifunctor+import Data.List (intersperse)+import Data.Tuple (swap)+import Prelude hiding (lookup)++data NMap k a =+      Branch { roots :: M.Map k (NMap k a) }+    | Leaf { leaf :: a }+    deriving Eq++infixr 0 .<+k .< xs = (k, Branch $ M.fromList xs)++infixr 0 .>+k .> a = (k, Leaf a)++infixr 0 <:>+m <:> n = m*n++instance (Show a, Show b) => Show (NMap a b) where+    show (Leaf a) = concat ["[", show a, "]"]+    show (Branch m) = concat $ ["["] ++ (intersperse ", " $ show' <$> (M.toList m)) ++ ["]"]+        where show' (k,a) = show k ++ " -> " ++ show a++drawNMap :: (Show k, Show a) => NMap k a -> String+drawNMap mt = unlines $ firstdraw mt where+    firstdraw (Leaf a) = concat ["{", show a, "}"] :[]+    firstdraw (Branch m) = firstdraw' (M.toList m)+    firstdraw' [] = ["()"]+    firstdraw' [(x,m)] = shift (show x ++ "─") (show x ++ " " *> " ") (draw m)+    firstdraw' ((x,m):xs) = (shift ("┌─" ++ show x ++ "─") ("│ " ++ (show x ++ "-" *> " ")) (draw m)) ++ (firstdraw'' xs)+    firstdraw'' [(x,m)] = shift ("└─" ++ show x ++ "─") ("└─" ++ show x ++ "─" *> " ") (draw m)+    firstdraw'' ((x,m):xs) = shift ("├─" ++ show x ++ "─") ("│ " ++ (show x ++ " " *> " ")) (draw m) ++ (firstdraw'' xs)+    draw (Leaf a) = concat ["──{", show a, "}"] :[]+    draw (Branch m) = draw' $ M.toList m+    draw' [] = "()":[]+    draw' [(x,m)] = shift ("──" ++ show x ++ "─") ("--" ++ show x ++ "-" *> " ") (draw m)+    draw' ((x,m):xs) = shift ("┬─" ++ show x ++ "─") ("│ " ++ (show x ++ " " *> " ")) (draw m) ++ (draw'' xs)+    draw'' [(x,m)] = shift ("└─" ++ show x ++ "─") ("  " ++ show x ++ " " *> " ") (draw m) +    draw'' ((x,m):xs) = shift ("├─" ++ show x ++ "─") ("│ " ++ (show x ++ " " *> " ")) (draw m) ++ (draw'' xs)+    shift first other = zipWith (++) (first : repeat other)++instance Ord k => Monoid (NMap k b) where+    mempty = Branch M.empty+    (Branch m1) `mappend` (Branch m2) = Branch $ M.unionWith mappend m1 m2+    fst `mappend` _ = fst++instance Functor (NMap k) where+    fmap f (Leaf a) = Leaf (f a)+    fmap f (Branch m) = Branch $ (fmap f) <$> m+    +instance Applicative (NMap k) where+    pure a = Leaf a+    Leaf f <*> t = f <$> t       +    Branch m <*> Leaf a = ($ a) <$> Branch m+    Branch m <*> Branch m' = Branch $ (Branch m <*>) <$> m'+    +instance Monad (NMap k) where+    return = pure+    Leaf a >>= f = f a+    Branch m >>= f = Branch $ (>>= f) <$> m+    +    +mapKeys :: Ord k2 => (k1 -> k2) -> NMap k1 a -> NMap k2 a+mapKeys f (Leaf a) = Leaf a+mapKeys f (Branch m) = Branch $ (mapKeys f) <$> (M.mapKeys f m)++mapWithKey :: (k -> a -> b) -> NMap k a -> NMap k b+mapWithKey _ (Leaf _) = error "can't map without a key"+mapWithKey f (Branch m) = Branch $ M.mapWithKey (\k mt -> mapWithKey0 f k mt) m++mapWithKey0 :: (k -> a -> b) -> k -> NMap k a -> NMap k b+mapWithKey0 f k (Leaf a) = Leaf (f k a)+mapWithKey0 f k (Branch m) = Branch $ M.mapWithKey (\k' mt -> mapWithKey0 f k' mt) m++mapWithKeys :: ([k] -> a -> b) -> NMap k a -> NMap k b+mapWithKeys f m = mapWithKeys0 f [] m+    where+        mapWithKeys0 f ks (Leaf a) = Leaf $ f ks a+        mapWithKeys0 f ks (Branch m) = Branch $ M.mapWithKey (\k mt -> mapWithKeys0 f (ks ++ [k]) mt) m++instance Foldable (NMap k) where+    foldr = fold++fold :: (a -> b -> b) -> b -> NMap k a -> b+fold f b (Leaf a) = f a b+fold f b (Branch m) = foldr (flip $ fold f) b m++instance Traversable (NMap k) where+    traverse f (Leaf a) = Leaf <$> f a    +    traverse f (Branch m) = Branch <$> (traverse (traverse f) m)++traverseKeys :: (Ord k2, Applicative t) => (k1 -> t k2) -> NMap k1 a -> t (NMap k2 a)+traverseKeys f = bitraverse f pure++traverseWithKey :: (Ord k, Applicative t) => (k -> a -> t b) -> NMap k a -> t (NMap k b)+traverseWithKey f = sequenceA . (mapWithKey f)++bitraverse :: (Applicative t, Ord k2) => (k1 -> t k2) -> (a1 -> t a2) -> NMap k1 a1 -> t (NMap k2 a2)+bitraverse _ g (Leaf a) = Leaf <$> g a+bitraverse f g (Branch m) = Branch <$> (traverseK2 f (bitraverse f g) m)++traverseK2 :: (Applicative t, Ord k2) => (k1 -> t k2) -> (a -> t b) -> M.Map k1 a -> t (M.Map k2 b)+traverseK2 f g = (M.fromList <$>) . (traverse (\(x,y) -> (,) <$> f x <*> g y)) . M.toList++bisequence :: (Applicative t, Ord k) => NMap (t k) (t a) -> t (NMap k a)+bisequence = bitraverse id id++mapKeysM :: (Ord k2, Monad m) => (k1 -> m k2) -> NMap k1 a -> m (NMap k2 a)+mapKeysM = traverseKeys++fromList :: Ord k => [(k,NMap k a)] -> NMap k a+fromList = Branch . M.fromList++fromKeys :: Ord k => [([k], a)] -> NMap k a+fromKeys xs = foldMap (uncurry branch) xs++toKeys :: Ord k => NMap k a -> [([k], a)]+toKeys = elems . (mapWithKeys (,))++elems :: NMap k a -> [a]+elems = foldr (:) []++-- alter :: (Maybe a -> Maybe a) -> [k] -> NMap k a -> NMap k a+-- alter f ks m = lookup ++delete :: Ord k => [k] -> NMap k a -> NMap k a+delete (k:[]) (Branch m) = Branch $ M.delete k m+delete (k:ks) (Branch m) = Branch $ M.adjust (delete ks) k m+delete [] nm = nm+delete _ l = l++delete0 :: Ord k => k -> NMap k a -> NMap k a+delete0 k (Branch m) = Branch $ M.delete k m+delete0 _ l = l++rootKeys :: NMap k a -> [k]+rootKeys (Leaf _) = error "0-depth trees don't have keys"+rootKeys (Branch m) = M.keys m++lookup :: Ord k => k -> NMap k a -> Maybe (Either (NMap k a) a)+lookup k (Leaf _) = Nothing+lookup k (Branch m) = case M.lookup k m of+    Just (Branch m') -> Just (Left $ Branch m')+    Just (Leaf a) -> Just (Right a)+    Nothing -> Nothing++(!) :: Ord k => NMap k a -> [k] -> a+(Leaf a)![] = a+(Leaf a)!_ = error "too many keys provided"+(Branch m)!(k:ks) = case m M.! k of+    (Leaf a') -> a'+    b -> b!ks+(Branch m)![] = error "not enough keys"+    ++member :: Ord k => k -> NMap k a -> Bool+member k (Branch m) = M.member k m+member _ _ = False++branch :: Ord k => [k] -> a -> NMap k a+branch ks a = foldr (\a b -> fromList [(a,b)]) (Leaf a) ks++branch0 :: Ord k => k -> a -> NMap k a+branch0 k a = fromList [k .> a]++insert :: Ord k => [k] -> a -> NMap k a -> NMap k a+insert ks a m = (branch ks a) `mappend` m++insert0 :: Ord k => k -> a -> NMap k a -> NMap k a +insert0 k a m = insert [k] a m++pt :: (Show k, Show a) => NMap k a -> IO ()+pt = putStr . drawNMap++test1 = fromList+    [ 1 .<+        [ 1 .> 'a'+        , 2 .< +            [ 1 .> 'b'+            , 2 .> 'c']+        , 3 .< +            [ 4 .> 'd' ] ]+    , 2 .> 'e' ]+        +test2 = fromList+    [ 1.< [ 2 .> 'a' ]]++test3 = fromList+    [ 1.< +        [ -2 .> 'a' ]+    , 3 .> 'b'+    , 4 .< [] ] ++test4 = fromList+    [ 1 .> (:[]) ]++test5 = fromList+    [ -1 .> (:[])+    , -2 .> (:"-d")]