Haskell: how to deal with the IO monad inside another monad?

just started to study the hackell - to love him in a week. At the moment, passing through the pain of monads, not yet, but I hope he clicks.

I am trying to compile a function similar to pythons walk (), but simpler. Given the path, I want to generate a list of tuples. Tuple for each subdirectory (allows you to simply assume that there will only be directories). The tuple will contain the path to the directory as its first element and a list of files that the directory contains as the second element.

I don't know if I explained this 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? Can I cancel them? Is it possible to deploy at least an internal IO? Is this normal?

I can’t even print such a return. Should I create an instance of the show to print correctly?

Most likely, there is a similar function in some haskell library, but this is for educational purposes. I want to learn. Therefore, any suggestions are welcome.

Thank you very much.

+4
source share
2 answers

Look at the types.

 map :: (a -> b) -> [a] -> [b] getCont :: FilePath -> IO (FilePath, [FilePath]) nd :: [FilePath] map getCont nd :: [IO (FilePath, FilePath)] 

Now, at the moment, the structure looks inside out. We have [IO a] , but want IO [a] . Stop! Google time. Generalizing to any ol 'monad, we hoogle [ma] β†’ m [a] . And so, sequence has such an exact signature. Therefore, instead of return :: a -> ma you should use sequence :: [ma] -> m [a] , for example:

 sequence (map getCont nd) 

Then everything will be ready. Please note that this is essentially identical to Kurt S's solution, because

 mapM f xs = sequence (map f xs) 
+4
source

This will open Control.Monad for mapM .

Then it

 return (map getcont nd) 

becomes

 mapM getcont nd 
+10
source

All Articles