diff --git a/filesystem-trees.cabal b/filesystem-trees.cabal
--- a/filesystem-trees.cabal
+++ b/filesystem-trees.cabal
@@ -1,12 +1,13 @@
 Name: filesystem-trees
-Version: 0.0
-Synopsis: Recursively manipulate and traverse filesystems as rose trees.
+Version: 0.1
+Synopsis: Recursively manipulate and traverse filesystems as lazy rose trees.
 Cabal-Version: >= 1.10
 License: BSD3
 License-File: LICENSE
 Author: Adam Curtis
 Maintainer: acurtis@spsu.edu
 Build-Type: Simple
+Category: System, Data
 
 library
   default-language: Haskell2010
@@ -15,12 +16,12 @@
   if impl(ghc >= 7.2) 
     default-extensions: Trustworthy
   build-depends:   base == 4.*
-                 , directory
-                 , filepath
-                 , unix
+                 , directory >= 1.1 && < 1.2
+                 , filepath >= 1.0 && < 2.0 
+                 , unix >= 2.0 && < 3.0
                  , containers >= 0.1 && < 0.6
-                 , data-lens
-                 , dlist
-                 , mtl
+                 , data-lens >= 2.0.1 && < 3.0
+                 , dlist >= 0.2 && < 1.0
+                 , mtl >= 1.0 && < 3.0
                  , cond >= 0.3 && < 0.5
   exposed-modules: System.File.Tree
diff --git a/src/System/File/Tree.hs b/src/System/File/Tree.hs
--- a/src/System/File/Tree.hs
+++ b/src/System/File/Tree.hs
@@ -12,13 +12,13 @@
        , TreeLens(..)
          -- *Retrieve directory trees from the filesystem
        , getDirectory, getDirectory'
-         -- **IO operations on directory trees
-         -- ***copy
+         -- *IO operations on directory trees
+         -- **copy
        , copyTo, copyTo_
-         -- ***move
+         -- **move
        , moveTo, moveTo_
        , mergeInto, mergeInto_
-         -- ***remove
+         -- **remove
        , remove, tryRemove, tryRemoveWith              
          -- * Operations on directory trees
          -- **basic operations
@@ -118,9 +118,11 @@
 mkFSTree :: FilePath -> FSForest -> FSTree
 mkFSTree a = FSTree . Node a . mapToTree
 
+-- |Efficiently maps 'FSTree' over a list. This is more efficient than map FSTree 
 mapFSTree :: Forest FilePath -> FSForest
 mapFSTree = unsafeCoerce
 
+-- |Efficiently maps toTree over a list. This is more effficient than map toTree
 mapToTree :: FSForest -> Forest FilePath
 mapToTree = unsafeCoerce
 
@@ -236,26 +238,36 @@
 mapM_ f t = mapM f t >> return ()
 
 -- |Applies a predicate to each path name in a filesystem forest, and removes
--- all unsuccessful paths from the result. 
--- 
--- Note that if a directory fails the predicate test, then all of its children are 
--- removed as well.
+-- all unsuccessful paths from the result. If a directory fails the predicate test, 
+-- then it will only be removed if all of its children also fail the test
 filter :: (FilePath -> Bool) -> FSForest -> FSForest
-filter p = fst . extract p
+filter p = runIdentity . filterM (return . p)
 
 -- |Find all sub-forests within a forest that match the given predicate.
 find :: (FilePath -> Bool) -> FSForest -> FSForest
 find p = snd . extract p
 
--- |A combination of a 'find' and a 'map'. This could be useful if you want to
--- handle certain directories specially from others within a sub-filesystem.
+-- |A generalization of 'find'. The first element of the result 
+-- represents the forest after removing all subtrees that match the given predicate, 
+-- and the second element is a list of trees that matched. This could be useful if 
+-- you want to handle certain directories specially from others within a 
+-- sub-filesystem.
 extract :: (FilePath -> Bool) -> FSForest -> (FSForest, FSForest)
 extract p = runIdentity . extractM (return . p)
 
 -- |Monadic 'filter'.
 filterM :: Monad m =>
            (FilePath -> m Bool) -> FSForest -> m FSForest
-filterM p = liftM fst . extractM p
+filterM p = foldrM (filter' . prependPaths) []
+  where filter' (Node path cs) ts =
+          ifM (p path)
+          (liftM ((:ts) . mkFSTree path) $ foldrM filter' [] cs)
+          (do
+              cs' <- foldrM filter' [] $ cs
+              return $ case cs' of
+                [] -> ts
+                _  -> mkFSTree path cs' : ts
+          )
 
 -- |Monadic 'find'.
 findM :: Monad m =>
@@ -273,13 +285,13 @@
   where 
     extract' t@(Node path cs) (ts, es)
       = ifM (p path)
-        ( do
-             (cs', es') <- foldrM extract' (ts, es) cs
-             let t' = mkFSTree path cs'
-             return (t' : ts, es' `append` es)
-        )
         (
-          return (ts, FSTree t `cons` es)
+             return (ts, FSTree t `cons` es)
+        )
+        (do
+            (cs', es') <- foldrM extract' ([], DL.empty) cs
+            let t' = mkFSTree path cs'
+            return (t' : ts, es' `append` es)
         )
 
 -- |Truncate a tree to a given maximum level, where root is level 0.  
