[Haskell-cafe] Re: Filesystem questions

Yitzchak Gale gale at sefer.org
Sun Oct 14 15:29:20 EDT 2007

Hi apfelmus,

I wrote:
>>>>> ...a tool for recursing through directories...
>>>>> How about a built-in function that represents a directory tree
>>>>> as a lazy Data.Tree?

>>> -- List all directories in the tree rooted at the given path
>>> traverseDirectories :: MonadIO m =>
>>>   TraversalDirection -> FilePath -> ListT m Directory

>> Or - getting back to the "lazy Data.Tree" idea -
>> we could define TreeT, analgous to ListT:
>> newtype TreeT m a = NodeT (m (a, TreeT (ListT m) a))
>> and give it a nice Monad instance. Then you can prune
>> and filter trees in a natural way, inside the monad.

apfelmus wrote:
> Eh, isn't that what ListT is already for?
> ...allows you to prune the directory tree in whatever way you like it.
> Here's an example top-down traversal that lists all non-directories:
>    allFiles :: MonadIO m => Directory -> m [FilePath]
>    allFiles d = runList $ do
>       f <- liftList $ contents d
>       if isDirectory f
>         then allFiles f
>         else return f
> In other words, ListT is like one of those iterators I keep hearing from
> the Python/Java/.../imperative world

Well, yes, you could also use it that way. And yes,
years ago they used to do it that way in Python.
Where every user has to build in the logic to
discover the tree structure manually, as they
iterate along.

But it turns out that it is much more natural and
convenient to be given the tree structure pre-built,
and then just traverse it. You need some laziness
to avoid visiting directories that you don't care about
and might be costly to visit.

Python currently uses generators to get the laziness.
Bryan uses unsafe IO, together with his "recursion predicates
and filter predicates".

My first proposal was just a minor modification of
Bryan's ideas. I presented the tree pre-traversed -
i.e., flattened, like Bryan, and also used his predicates.
But I used ListT to provide the laziness instead of
unsafe IO.

My second proposal is to present the entire tree inside
a lazy monad transformer. While the internal plumbing
is slightly more complex, I think it will provide the most
natural and convenient interface for the end user
(who needs not understand all that monad stuff).


More information about the Haskell-Cafe mailing list