Reputation: 10353
just started learning haskell - love it after a week. At the moment going through the monads pain, not there yet but hopefully it will click.
I am trying to put together a function similar to pythons walk() but simpler. Given a path I want to generate list of tuples. A tuple for each sub directory (lets just assume that there will be only directories). The tuple would contain path of the directory as its first element and list of files the directory contains as the second element.
I don't know if I explained it correctly but here is the code:
walkDir :: String -> IO [IO (FilePath, [FilePath])]
walkDir path = do
dir <- getDirectoryContents path
let nd = [x | x <- dir, notElem x [".",".."]]
return (map getcont nd)
where
getcont path = do
cont <- getDirectoryContents path
return (path,cont)
My concern is IO inside IO and how to deal with it?? Is it possible to cancel them out? Is it possible to unwrap at least the internal IO? Is this kind of return normal?
I can not even print this kind of return. Do I have to create an instance of show for this to be printed correctly?
There most likely exist a similar function in some haskell library but this is for educational purpose. I want to learn. So any suggestions welcome.
Thank you very much.
Upvotes: 4
Views: 929
Reputation: 53665
Let's look at the types.
map :: (a -> b) -> [a] -> [b]
getCont :: FilePath -> IO (FilePath, [FilePath])
nd :: [FilePath]
map getCont nd :: [IO (FilePath, FilePath)]
Now, at this point, the structure looks inside-out. We have [IO a]
but we want IO [a]
. Stop! Hoogle time. Generalizing for any ol' monad, we hoogle [m a] -> m [a]. Lo and behold, sequence
has that precise type signature. So instead of return :: a -> m a
you should use sequence :: [m a] -> m [a]
, like this:
sequence (map getCont nd)
Then you'll be all set. Notice that this is essentially identical to Kurt S's solution, because
mapM f xs = sequence (map f xs)
Upvotes: 4
Reputation: 4034
Check out Control.Monad for mapM
.
Then this
return (map getcont nd)
becomes
mapM getcont nd
Upvotes: 10