5
votes

I'm still figuring out Haskell, especially the IO monad.

I have a list of directory paths, e.g.,

["/some/path", "/another/path", "/yet/another/path", "/still/more"]

and I want to map this list into a list of fully-qualified contents of each of these paths (without . and ..), like this:

["/some/path/file.1", "/some/path/somedir", "/some/path/file.2", "/another/path/file.a", "/another/path/a/directory", "/another/path/file.b", "/still/more/file.alpha", ...]

I figure I could do this with some kind of double-map, like this:

pathItems <- mapM (\pd -> MapM (\contents -> (pd </>) contents) (getDirectoryContents pd) pathDirs

but this doesn't work. The error I'm getting is this:

program.hs:27:56:
    Couldn't match type `[]' with `IO'
    Expected type: IO Char
      Actual type: FilePath
    In the expression: (pd </>) contents
    In the first argument of `mapM', namely
      `(\ contents -> (pd ) contents)'

program.hs:27:84:
    Couldn't match expected type `[FilePath]'
                with actual type `IO [FilePath]'
    In the second argument of `mapM', namely
      `(getDirectoryContents pathDir)'
    In the expression:
      mapM
        (\ contents -> (pd </>) contents)
        (getDirectoryContents pd)
1
Could you post a minimum working example, instead of just the line which throws the error?G Philip
oh wait (sorry): you want to inspect each of theses paths, get all the files in there and concatMap them together into a single list - right?Random Dev
From a quick look you might need (\ contents -> return $ (pd </>) contents) instead. But this looks too complex, probably fmap (map (pd </>)) (getDirectoryContents pd) can replace the inner mapM.chi

1 Answers

3
votes

A possible solution (importing System.IO System.Directory System.FilePath Control.Applicative):

concat <$> mapM (\pd -> map (pd </>) <$> getDirectoryContents pd) pathDirs
                                   -- ^ this is to work under IO (..)
                    --  ^ this is to affect what's under IO [..]
        -- ^ this returns IO [[FilePath]]

There might be some way to simplify it further.