Our predicates can only look at filenames. This excludes a wide variety of interesting behaviors—for instance, what if we’d like to list files greater than a given size?
An easy reaction to this is to reach for IO: instead of our predicate being of type FilePath -> Bool, why don’t we change it to FilePath -> IO Bool? This would let us perform arbitrary I/O as part of our predicate. As appealing as this might seem, it’s also potentially a problem: such a predicate could have arbitrary side effects, since a function with return type IO a can have whatever side effects it pleases.
Let’s enlist the type system in our quest to write more predictable, less buggy code; we’ll keep predicates pure by avoiding the taint of “IO.” This will ensure that they can’t have any nasty side effects. We’ll feed them more information, too, so that they can gain the expressiveness we want without also becoming potentially dangerous.
System.Directory module provides a useful, albeit limited,
set of file metadata:
We can use
doesDirectoryExist to determine
whether a directory entry is a file or a directory. There are not yet
portable ways to query for other file types that have become widely
available in recent years, such as named pipes, hard links, and symbolic
:type doesFileExistdoesFileExist :: FilePath -> IO Bool
doesFileExist "."Loading package old-locale-22.214.171.124 ...