Advertisement
Guest User

Haskell lazy I/O and closing files 2

a guest
Jun 5th, 2010
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Control.Monad
  2. import Data.Digest.MD5 (hash)
  3. import Data.Word
  4. import List (sort)
  5. import Prelude
  6. import System.Directory
  7. import System.FilePath
  8. import System.IO
  9. import Text.Printf (printf)
  10. import qualified Data.ByteString.Lazy as BS
  11.  
  12. main :: IO ()
  13.  
  14. main = putStr . unlines =<< getList "."
  15.  
  16. getList :: FilePath -> IO [String]
  17.  
  18. getList p =
  19.     let getFileLine path = liftM (\c -> (hex c) ++ " " ++ path) (getFileHash path)
  20.     in mapM getFileLine =<< getRecursiveContents p
  21.  
  22. hex :: [Word8] -> String
  23.  
  24. hex = concatMap (\x -> printf "%0.2x" (toInteger x))
  25.  
  26. getFileHash :: FilePath -> IO [Word8]
  27.  
  28. getFileHash path = do
  29.     handle <- openFile path ReadMode
  30.     contents <- BS.hGetContents handle
  31.     let !hashed = hash $ BS.unpack contents
  32.     hClose handle
  33.     return hashed
  34.  
  35. getRecursiveContents :: FilePath -> IO [FilePath]
  36.  
  37. getRecursiveContents topdir = do
  38.     names <- getDirectoryContents topdir
  39.  
  40.     let properNames = filter (`notElem` [".", ".."]) names
  41.  
  42.     paths <- concatForM properNames $ \name -> do
  43.         let path = topdir </> name
  44.  
  45.         isDirectory <- doesDirectoryExist path
  46.         if isDirectory
  47.             then getRecursiveContents path
  48.             else do
  49.                 isFile <- doesFileExist path
  50.                 if isFile
  51.                     then return [path]
  52.                     else return []
  53.  
  54.     return (sort paths)
  55.  
  56. concatForM :: (Monad m) => [a1] -> (a1 -> m [a]) -> m [a]
  57.  
  58. concatForM xs f = liftM concat (forM xs f)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement