views:

166

answers:

3

I'm needing some Ints to use as seed to random number generation and so I wanted to use the old trick of using the system time as seed.

So I tried to use the Data.Time package and I managed to do the following:

 import Data.Time.Clock

 time = getCurrentTime >>= return . utctDayTime

When I run time I get things like:

 Prelude Data.Time.Clock> time
 55712.00536s

The type of time is IO DiffTime. I expected to see an IO Something type as this depends on things external to the program. So I have two questions:

a) Is it possible to somehow unwrap the IO and get the underlying DiffTime value?

b) How do I convert a DiffTime to an integer with it's value in seconds? There's a function secondsToDiffTime but I couldn't find its inverse.

+3  A: 

a) Of course it is possible to get the DiffTime value; otherwise, this function would be rather pointless. You'll need to read up on monads. This chapter and the next of Real World Haskell has a good introduction.

b) The docs for DiffTime say that it's an instance of the Real class, i.e. it can be treated as a real number, in this case the number of seconds. Converting it to seconds is thus a simple matter of chaining conversion functions:

diffTimeToSeconds :: DiffTime -> Integer
diffTimeToSeconds = floor . toRational
Thomas
You lose the picoseconds this way, however. I usually do `truncate . (fromIntegral precision * ) . toRational . utctDayTime`, which gives you the number of picoseconds. (And for seeding a RNG, using this value lets you have more than one initial state per second, which is important in many applications.)
jrockway
(oh, and precision = 10000000000000)
jrockway
+4  A: 

Is it possible to somehow unwrap the IO and get the underlying DiffTime value?

Yes. There are dozens of tutorials on monads which explain how. They are all based on the idea that you write a function that takes DiffTime and does something (say returning IO ()) or just returns an Answer. So if you have f :: DiffTime -> Answer, you write

time >>= \t -> return (f t)

which some people would prefer to write

time >>= (return . f) 

and if you have continue :: DiffTime -> IO () you have

time >>= continue

Or you might prefer do notation:

do { t <- time
   ; continue t  -- or possibly return (f t)
   }

For more, consult one of the many fine tutorals on monads.

Norman Ramsey
I'd think for simplicity, especially for a beginner, you could omit the parenthesis in return . f and whow the whitespace-style do-syntax?
codebliss
@codebliss: for a beginner I wanted to make things very explicit and so not require the reader to understand the details of operator precedence or layout
Norman Ramsey
+3  A: 

If you are planning to use the standard System.Random module for random number generation, then there is already a generator with a time-dependent seed initialized for you: you can get it by calling getStdGen :: IO StdGen. (Of course, you still need the answer to part (a) of your question to use the result.)

Reid Barton