@@ -118,9 +118,11 @@ type FSForest = [FSTree]
118118mkFSTree :: FilePath -> FSForest -> FSTree
119119mkFSTree a = FSTree . Node a . mapToTree
120120
121+ -- | Efficiently maps 'FSTree' over a list. This is more efficient than map FSTree
121122mapFSTree :: Forest FilePath -> FSForest
122123mapFSTree = unsafeCoerce
123124
125+ -- | Efficiently maps toTree over a list. This is more effficient than map toTree
124126mapToTree :: FSForest -> Forest FilePath
125127mapToTree = unsafeCoerce
126128
@@ -236,34 +238,41 @@ mapM_ :: Monad m => (FilePath -> m b) -> FSTree -> m ()
236238mapM_ f t = mapM f t >> return ()
237239
238240-- | Applies a predicate to each path name in a filesystem forest, and removes
239- -- all unsuccessful paths from the result.
240- --
241- -- Note that if a directory fails the predicate test, then all of its children are
242- -- removed as well.
241+ -- all unsuccessful paths from the result. If a directory fails the predicate test,
242+ -- then it will only be removed if all of its children also fail the test
243243filter :: (FilePath -> Bool ) -> FSForest -> FSForest
244- filter p = fst . extract p
244+ filter p = runIdentity . filterM ( return . p)
245245
246246-- | Find all sub-forests within a forest that match the given predicate.
247247find :: (FilePath -> Bool ) -> FSForest -> FSForest
248- find p = snd . extract ( not . p)
248+ find p = snd . extract p
249249
250- -- | A generalization of 'find' and 'filter' . The first element of the result
251- -- represents the forest after filtering with the given predicate, and the second
252- -- element is a list of trees that didn't match the predicate . This could be useful
253- -- if you want to handle certain directories specially from others within a
250+ -- | A generalization of 'find'. The first element of the result
251+ -- represents the forest after removing all subtrees that match the given predicate,
252+ -- and the second element is a list of trees that matched . This could be useful if
253+ -- you want to handle certain directories specially from others within a
254254-- sub-filesystem.
255255extract :: (FilePath -> Bool ) -> FSForest -> (FSForest , FSForest )
256256extract p = runIdentity . extractM (return . p)
257257
258258-- | Monadic 'filter'.
259259filterM :: Monad m =>
260260 (FilePath -> m Bool ) -> FSForest -> m FSForest
261- filterM p = liftM fst . extractM p
261+ filterM p = foldrM (filter' . prependPaths) []
262+ where filter' (Node path cs) ts =
263+ ifM (p path)
264+ (liftM ((: ts) . mkFSTree path) $ foldrM filter' [] cs)
265+ (do
266+ cs' <- foldrM filter' [] $ cs
267+ return $ case cs' of
268+ [] -> ts
269+ _ -> mkFSTree path cs' : ts
270+ )
262271
263272-- | Monadic 'find'.
264273findM :: Monad m =>
265274 (FilePath -> m Bool ) -> FSForest -> m FSForest
266- findM p = liftM snd . extractM (notM . p)
275+ findM p = liftM snd . extractM p
267276
268277-- | Monadic 'extract'.
269278extractM :: Monad m =>
@@ -276,13 +285,13 @@ extractM_ p = foldrM extract' ([], DL.empty) . P.map prependPaths
276285 where
277286 extract' t@ (Node path cs) (ts, es)
278287 = ifM (p path)
279- ( do
280- (cs', es') <- foldrM extract' (ts, es) cs
281- let t' = mkFSTree path cs'
282- return (t' : ts, es' `append` es)
283- )
284288 (
285- return (ts, FSTree t `cons` es)
289+ return (ts, FSTree t `cons` es)
290+ )
291+ (do
292+ (cs', es') <- foldrM extract' ([] , DL. empty) cs
293+ let t' = mkFSTree path cs'
294+ return (t' : ts, es' `append` es)
286295 )
287296
288297-- | Truncate a tree to a given maximum level, where root is level 0.
0 commit comments