Yesterday I decided to leave the relative safety of solving exercises in tutorials and instead try solving a small problem I had at work. I had pairs of times (points in time, like Wednesday November 8 01:17) and I needed the difference between them. Not a tricky problem by any stretch of the imagination, but I figured I had to start using Haskell at some point. I might as well make this that point.
I started out by playing around with
gchi. One thing that seemed missing was a function that took a
String and tried to interpret it as a
CalendarTime. After a mail to Haskell Cafe I discovered
I found myself programming top-down, stubbing “sub functions” while trying to get the types of the current function right. It turns out I was “lucky” and there wasn’t many monads involved, but still I did run into some problems with mixing
do notation and
case. In the end I split out those constructs and kept only the most basic syntactical constructs inside the
Here’s the end result, not the most functional piece of Haskell code ever seen, but it’s the first time I dip my toes in the sea of Haskell without a tutorial life-west.
module Main where import System.Locale import System.Time import System.Environment import MissingH.Time.ParseDate diffAndToString :: CalendarTime -> CalendarTime -> String diffAndToString s e = let sC = toClockTime s eC = toClockTime e diff = normalizeTimeDiff $ diffClockTimes eC sC in formatTimeDiff defaultTimeLocale "%R" diff calcDiff :: String -> String -> Either String String calcDiff start end = let -- I had problems using %Y, so I'm using %C%y instead sT = parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" start eT = parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" end in case (sT, eT) of (Nothing, _) -> Left "start time" (_, Nothing) -> Left "end time" (Just s, Just e) -> Right $ diffAndToString s e resultString :: String -> String -> String resultString s e = let calculatedDiff = calcDiff s e in case calculatedDiff of (Left s) -> "Bad " ++ s (Right s) -> s main :: IO () main = do args <- getArgs putStrLn $ resultString (args !! 0) (args !! 1)