packages feed

path-tree (empty) → 0.2.0.0

raw patch · 4 files changed

+177/−0 lines, 4 filesdep +basedep +containersdep +relude

Dependencies added: base, containers, relude

Files

+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2022 Sridhar Ratnakumar++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,2 @@+# path-tree+
+ path-tree.cabal view
@@ -0,0 +1,84 @@+cabal-version:      2.4+name:               path-tree+version:            0.2.0.0+license:            MIT+copyright:          2022 Sridhar Ratnakumar+maintainer:         srid@srid.ca+author:             Sridhar Ratnakumar+category:           Data Structures++-- A short (one-line) description of the package.+synopsis: `Data.Tree` for file paths++-- A longer description of the package.+description: `Data.Tree` for file paths++-- A URL where users can report bugs.+bug-reports: https://github.com/srid/pathtree++extra-source-files:+  LICENSE+  README.md++library+  build-depends:+    , base >=4.13.0.0 && <=4.18.0.0+    , containers+    , relude++  mixins:+    base hiding (Prelude),+    relude (Relude as Prelude, Relude.Container.One),+    relude++  ghc-options:+    -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns+    -Wmissing-deriving-strategies -Wunused-foralls -Wunused-foralls+    -fprint-explicit-foralls -fprint-explicit-kinds++  default-extensions:+    NoStarIsType+    BangPatterns+    ConstraintKinds+    DataKinds+    DeriveDataTypeable+    DeriveFoldable+    DeriveFunctor+    DeriveGeneric+    DeriveLift+    DeriveTraversable+    DerivingStrategies+    DerivingVia+    EmptyCase+    EmptyDataDecls+    EmptyDataDeriving+    ExistentialQuantification+    ExplicitForAll+    FlexibleContexts+    FlexibleInstances+    GADTSyntax+    GeneralisedNewtypeDeriving+    ImportQualifiedPost+    KindSignatures+    LambdaCase+    MultiParamTypeClasses+    MultiWayIf+    NumericUnderscores+    OverloadedStrings+    PolyKinds+    PostfixOperators+    RankNTypes+    ScopedTypeVariables+    StandaloneDeriving+    StandaloneKindSignatures+    TupleSections+    TypeApplications+    TypeFamilies+    TypeOperators+    ViewPatterns++  exposed-modules:+    Data.Tree.Path++  hs-source-dirs:     src+  default-language:   Haskell2010
+ src/Data/Tree/Path.hs view
@@ -0,0 +1,70 @@+module Data.Tree.Path where++import Data.List qualified as List+import Data.List.NonEmpty qualified as NE+import Data.Tree (Tree (Node))+import Data.Tree qualified as Tree++treeInsertPath :: Eq a => NonEmpty a -> [Tree a] -> [Tree a]+treeInsertPath =+  treeInsertPathMaintainingOrder void++-- | Insert a node by path into a tree with descendants that are ordered.+--+-- Insertion will guarantee that descendants continue to be ordered as expected.+--+-- The order of descendents is determined by the given order function, which+-- takes the path to a node and return that node's order. The intention is to+-- lookup the actual order value which exists *outside* of the tree+-- datastructure itself.+treeInsertPathMaintainingOrder :: (Eq a, Ord ord) => (NonEmpty a -> ord) -> NonEmpty a -> [Tree a] -> [Tree a]+treeInsertPathMaintainingOrder ordF path t =+  orderedTreeInsertPath ordF (toList path) t []+  where+    orderedTreeInsertPath :: (Eq a, Ord b) => (NonEmpty a -> b) -> [a] -> [Tree a] -> [a] -> [Tree a]+    orderedTreeInsertPath _ [] trees _ =+      trees+    orderedTreeInsertPath pathOrder (top : rest) trees ancestors =+      case treeFindChild top trees of+        Nothing ->+          let newChild = Node top $ orderedTreeInsertPath pathOrder rest [] (top : ancestors)+           in sortChildrenOn pathOrder (trees <> one newChild)+        Just (Node _match grandChildren) ->+          let oneDead = treeDeleteChild top trees+              newChild = Node top $ orderedTreeInsertPath pathOrder rest grandChildren (top : ancestors)+           in sortChildrenOn pathOrder (oneDead <> one newChild)+      where+        treeFindChild x xs =+          List.find (\n -> Tree.rootLabel n == x) xs+        sortChildrenOn f =+          sortOn $ (\s -> f $ NE.reverse $ s :| ancestors) . Tree.rootLabel++treeDeletePath :: Eq a => NonEmpty a -> [Tree a] -> [Tree a]+treeDeletePath =+  treeDeletePathWithLastBehavingAs $ \lastInPath ts ->+    List.deleteBy (\x y -> Tree.rootLabel x == Tree.rootLabel y) (Node lastInPath []) ts++treeDeleteLeafPath :: Eq a => NonEmpty a -> [Tree a] -> [Tree a]+treeDeleteLeafPath =+  treeDeletePathWithLastBehavingAs $ \lastInPath ts ->+    case ts of+      [t] -> [t | Tree.rootLabel t /= lastInPath]+      _ -> ts++treeDeletePathWithLastBehavingAs :: forall a. Eq a => (a -> [Tree a] -> [Tree a]) -> NonEmpty a -> [Tree a] -> [Tree a]+treeDeletePathWithLastBehavingAs f slugs =+  go (toList slugs)+  where+    go :: [a] -> [Tree a] -> [Tree a]+    go [] t = t+    go [p] ts =+      f p ts+    go (p : ps) t =+      t <&> \node@(Node x xs) ->+        if x == p+          then Node x $ go ps xs+          else node++treeDeleteChild :: Eq a => a -> [Tree a] -> [Tree a]+treeDeleteChild x =+  List.deleteBy (\p q -> Tree.rootLabel p == Tree.rootLabel q) (Node x [])