Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Haskell lazy I/O and closing files 2

By: a guest on Jun 5th, 2010  |  syntax: Haskell  |  size: 1.36 KB  |  views: 226  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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)
clone this paste RAW Paste Data