doesFileExist "foo.txt" is an IO Bool , which means that its result depends on the state of the outside world.
You are on the right track with map doesFileExist files - this expression will return [IO Bool] or a list of world-dependent expressions. In fact, an IO expression containing a list of bools is needed. You can get this with sequence :
sequence :: Monad m => [ma] -> m [a]
or, since you just use the sequence / map, the mapM helper function:
mapM :: Monad m => (a -> mb) -> [a] -> m [b] mapM f xs = sequence (map f xs)
Let's get back to your code. Here is the version using mapM , with comments:
import System.Directory -- When figuring out some unfamiliar libraries, I like to use type annotations -- on all top-level definitions; this will help you think through how the types -- match up, and catch errors faster. allFilesPresent :: [String] -> IO Bool -- Because allFilesPresent returns a computation, we can use do-notation to write -- in a more imperative (vs declarative) style. This is sometimes easier for students -- new to Haskell to understand. allFilesPresent files = do -- Run 'doesFileExist' tests in sequence, storing the results in the 'filesPresent' -- variable. 'filesPresent' is of type [Bool] filesPresent <- mapM doesFileExist files -- The computation is complete; we can use the standard 'and' function to join the -- list of bools into a single value. return (and filesPresent)
The alternate version uses a more declarative syntax; this is probably what the experienced Haskell programmer wrote:
allFilesPresent :: [String] -> IO Bool allFilesPresent = fmap and . mapM doesFileExist
source share