[Haskell-cafe] background question about IO monad

Uwe Hollerbach uhollerbach at gmail.com
Tue Feb 5 23:44:27 EST 2008


Hello, haskellers, I have a question for you about the IO monad. On
one level, I seem to be "getting" it, at least I seem to be writing
code that does what I want, but on another level I am almost certainly
not at all clear on some concepts. In various tutorials around the
web, I keep finding this notion that the IO monad is "one-way", that
you can put stuff into it, but you can't take it out. (And, damn, some
of the contortions I went through while trying to figure out how to do
exceptions in my little scheme interpreter certainly bear that out! I
was sure beating my head against liftIO et al for a fair while...) But
let me post some code snippets here:

> lispUTCTime [] = doIOAction (getClockTime) toS allErrs
>   where toS val = String (calendarTimeToString (toUTCTime val))

> lispUTCTime [IntNumber n] =
>   return (String (calendarTimeToString (toUTCTime (TOD n 0))))

This is a little function I added to the interpreter a couple of days
ago: if you enter (UTCtime) with no arguments, it gets the current
time and formats it as UTC: like so; this came from the first
alternative above:

  lisp> (UTCtime)
  "Wed Feb  6 03:57:45 UTC 2008"

and if you give an argument, you get that interpreted as a number of
seconds since epoch, and that gets formatted as UTC; this is from the
second alternative above:

  lisp> (UTCtime 1.203e9)
  "Thu Feb 14 14:40:00 UTC 2008"

And here's the doIOAction routine: I wrote this, it's not some
system-level routine.

> doIOAction action ctor epred =
>   do ret <- liftIO (try action)
>      case ret of
>           Left err -> if epred err
>                          then throwError (Default (show err))
>                          else return (Bool False)
>           Right val -> return (ctor val)

OK, with all that as background, on one level I understand why I need
the doIOAction routine in the first version of lispUTCTime: I'm
calling getClockTime, that's an IO action, so I enter the IO monad,
get the time, and return: all is cool. In the second version, all I'm
doing is taking a number and interpreting it as a time, and writing
that in a particular format; again, no problem.

But after that, it sure seems to me as if I've taken data out of the
IO monad... haven't I? Given that the second alternative never entered
doIOAction and that after both are done I have a string of characters,
prettily formatted to indicate a time, that's what it feels like to
this unwashed C programmer.

So, what's going on there? What's the difference between the two
alternatives? I would appreciate any enlightenment you can send my
way!

regards,
Uwe


More information about the Haskell-Cafe mailing list