9/05/2009
I’ve released my first package, up now on hackage (haddock docs should be generated soon). The module provides a simple data structure that mirrors a directory tree, and some useful functions for doing IO on directories of files. You can read more about it here.
It’s very likely there are some bugs, especially related to cross platform issues with file names and paths. The module is also fairly bare, so please send me any requests for functionality that I haven’t thought of, as well as any bugs you might find.
You can install it with:
$ cabal install directory-tree
And get the source with:
$ darcs get http://coder.bsimmons.name/code/DirectoryTree/
I hope this is useful to someone!
30/04/2009
UPDATE: I’ve just released this as my first package on hackage. You can read more and write any comments here.
I just put together a library that provides a simple tree data structure to represent the structure of files and directories in the OS. It provides some simple IO functions like readDirectory (analogous to readFile) which “opens” a directory, returning a DirTree of Strings in the IO monad.
The nice thing is that by defining a simple instance for Traversable (and the default instances for Foldable and Functor that we get for free) we get a whole array of nice functions which we can apply to directory structures! For example, we can combine all the text in a directory of files with:
combineFiles :: FilePath -> IO [Char]
combineFiles d = do (_ :/ t) <- readDirectory d
return $ F.foldr1 (++) t
(the (_:/t) portion ignores the base directory returned). The DirTree type also includes a constructor for handling failures. Here is the type definition:
data DirTree a = Dir { name :: FileName,
contents :: [DirTree a] }
| File { name :: FileName,
file :: a }
| Failed { name :: FileName,
err :: Exception }
deriving (Show, Eq)
I have created a file with three examples:
- in the first we simulate the command
darcs initialize to illustrate creating a directory of files by hand, and writing it to disk.
- second, we show combining several different directories from around the filesystem and assembling the into a new tree structure.
- lastly, we use our
readDirectoryWith (with Data.ByteString.readFile), and our Foldable instance to hash all the files in a directory structure (with Thomas DuBuisson’s pureMD5 package) and compare it to the hash of a different directory to see if the contents match exactly
There are probably bugs, and there are many useful functions I can think of to add if people think this is useful. I would be interested in hearing your thoughts on the interface, on any functionality you would like added, and anything else!
You can get the module and examples.hs with:
$ darcs get http://coder.bsimmons.name/code/DirectoryTree/
25/04/2009
I’m working on a module called DirectoryTree, a simple tree structure mirroring the structure of a directory tree in the outside world, with functions to hopefully make it easy to do useful things (I’m not sure if something like this already exists). Here is the data-type:
data DirTree a = Dir { name :: String,
files :: [a],
directories :: [DirTree a] }
| Fail String
I would like to do things like map over a DirTree of FilePaths, returning a tree (in the IO monad) of Handles… so the code involves a lot of slogging through the IO monad, which I’m not totally comfortable with yet.
I’m feeling out how to proceed with the above and begin to define this function:
ioMap :: (a -> IO b) -> DirTree a -> IO (DirTree b)
…there’s something happening here but I don’t know what it is; let’s see what Hoogle can tell me about this abstraction. I take the type definition and plug it into firefox’s hoogle search plugin and voila!; I’m presented with the following matches:
Data.Traversable:
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
I see that mapM from Data.Traversable looks like what I want, and traverse also looks useful.
I learned something, and have an idea of how to proceed, and that’s why I love hoogle :)