
Hello list, I'm new to Haskell and I'm trying to learn how to write elegant code using Haskell. I decided to convert the following small tool, written in ruby: =========================================================== #! /usr/bin/env ruby require 'pathname' BASENAMES = %w{ mail.log thttpd.log } ARCHIVEDIR = Pathname.new '/var/log/archive' LOGDIR = Pathname.new '/var/log' class Pathname def glob glob_pattern Pathname.glob self.join(glob_pattern) end def timestamp stat.mtime.strftime '%Y%m%d' end end for basename in BASENAMES for oldname in LOGDIR.glob "#{basename}.*.gz" newname = ARCHIVEDIR.join "#{basename}.#{oldname.timestamp}.gz" puts "mv #{oldname} #{newname}" File.rename oldname, newname end end =========================================================== My solution in Haskell is: =========================================================== import System.Directory (getDirectoryContents, getModificationTime, renameFile) import System.Locale (defaultTimeLocale) import System.Time (ClockTime, toUTCTime, formatCalendarTime) import Text.Regex (mkRegex, matchRegex) import Maybe import Control.Monad logdir, archivedir :: String logfiles :: [String] logfiles = [ "mail.log", "thttpd.log" ] logdir = "/var/log" archivedir = "/var/log/archive" basename :: String -> String basename filename = head . fromMaybe [""] $ matchRegex rx filename where rx = mkRegex "^(.+)(\\.[0-9]+\\.gz)$" isLogfile :: String -> Bool isLogfile filename = basename filename `elem` logfiles timestamp :: ClockTime -> String timestamp time = formatCalendarTime defaultTimeLocale "%Y%m%d" (toUTCTime time) makeOldname :: String -> String makeOldname fn = logdir ++ '/' : fn makeNewname :: String -> String -> String makeNewname bn ts = archivedir ++ '/' : bn ++ '.' : ts ++ ".gz" move :: String -> String -> IO () move oldname newname = do putStrLn $ "mv " ++ oldname ++ ' ' : newname renameFile oldname newname main :: IO () main = do files <- liftM (filter isLogfile) (getDirectoryContents logdir) let oldnames = map makeOldname files times <- mapM getModificationTime oldnames let newnames = zipWith makeNewname (map basename files) (map timestamp times) zipWithM_ move oldnames newnames =========================================================== Ok, the tool written in Haskell works. But, to me, the source doesn't look very nice and even it is larger than the ruby solution, and more imporant, the programm flow feels (at least to me) not very clear. Are there any libraries available to make writing such tools easier? How can I made the haskell source looking more beautiful? Michael Roth