Getting real with Haskell
- Magnus Therning
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 System.Time
and System.Locale
in 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 MissingH
.
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 let
, where
, and case
. In the end I split out those constructs and kept only the most basic syntactical constructs inside the do
.
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
= toClockTime s
sC = toClockTime e
eC = normalizeTimeDiff $ diffClockTimes eC sC
diff in
"%R" diff
formatTimeDiff defaultTimeLocale
calcDiff :: String -> String -> Either String String
=
calcDiff start end let
-- I had problems using %Y, so I'm using %C%y instead
= parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" start
sT = parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" end
eT 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
= calcDiff s e
calculatedDiff in
case calculatedDiff of
Left s) -> "Bad " ++ s
(Right s) -> s
(
main :: IO ()
= do
main <- getArgs
args putStrLn $ resultString (args !! 0) (args !! 1)