[Haskell-cafe] How to write elegant Haskell programms? (long
posting)
Michael Roth
mroth at nessie.de
Mon Jan 29 14:14:55 EST 2007
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 155 bytes
Desc: OpenPGP digital signature
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070129/bb3f0a2a/signature.bin
More information about the Haskell-Cafe
mailing list