[Haskell-beginners] until and Time
Daniel Fischer
daniel.is.fischer at web.de
Wed Dec 31 22:54:44 EST 2008
Am Donnerstag, 1. Januar 2009 04:18 schrieb Steve Klabnik:
> Hello everyone. I have a quick question about Time.
>
> I was talking about Haskell on the Arch Linux forums today, and someone was
> trying to put together code that would print a series of periods for, say,
> 5 minutes. I felt like using 'until' would be the most correct way of going
> about it, but when I tried to do it...
>
>
> import Time
>
> makeLater :: ClockTime -> ClockTime
> makeLater t = addToClockTime (TimeDiff 0 0 0 0 0 5 0) t
>
> updateTime :: ClockTime -> ClockTime
> updateTime t = t
>
> main = do
> start <- getClockTime
> until ((==) $ makeLater start) (updateTime) start
> putStrLn "done"
>
> Now, updateTime isn't correct. And this wouldn't print any periods. But GHC
> is giving me errors:
>
> $ runhaskell temp.hs
>
> temp.hs:11:2:
> Couldn't match expected type `IO t'
> against inferred type `ClockTime'
> In the expression:
> until ((==) $ makeLater start) (updateTime) start
> In a 'do' expression:
> until ((==) $ makeLater start) (updateTime) start
> In the expression:
> do start <- getClockTime
> until ((==) $ makeLater start) (updateTime) start
> putStrLn "done"
>
> I'm not sure where IO t is coming from at all. Am I even on the right
> track? How would you write this code?
Since it appears as a statement in the main do-block, ghc expects "until ..."
to have type IO t. But as
Prelude> :t until
until :: (a -> Bool) -> (a -> a) -> a -> a
until ((==) $ makeLater start) (updateTime) start
actually has type ClockTime, so can't appear as a statement in a do-block,
that's what ghc tells you.
Since you want a timeout, which involves IO, you must do something in IO.
You can define a general control structure (I'm sure that is already defined
somewhere, but I can't be bothered to hoogle it now)
untilM :: (Monad m) => (a -> m Bool) -> (a -> m a) -> a -> m a
untilM test action value = do
stop <- test value
if stop then return value
else do
newval <- action value
untilM test action newval
and then
isLaterThan :: ClockTime -> IO Bool
isLaterThan end = do
now <- getClockTime
return (end < now)
main = do
start <- getClockTime
let end = addToClockTime (TimeDiff 0 0 0 0 0 5 0) start
untilM (\_ -> isLaterThan end) (\_ -> putChar '.') ()
putStr "\n"
More information about the Beginners
mailing list