2010-01-21 16 views
10

Necesito algunos Int s para usar como semilla para la generación de números aleatorios y por eso quería usar el viejo truco de usar la hora del sistema como semilla.¿Cómo obtener la hora del sistema en Haskell usando Data.Time.Clock?

así que traté de usar el paquete Data.Time y me las arreglé para hacer lo siguiente:

import Data.Time.Clock 

time = getCurrentTime >>= return . utctDayTime 

Cuando corro vez que tengo cosas como:

Prelude Data.Time.Clock> time 
55712.00536s 

El tipo de time es IO DiffTime. Esperaba ver un tipo IO Something ya que esto depende de cosas externas al programa. Entonces tengo dos preguntas:

a) ¿Es posible de alguna manera desenvolver el IO y obtener el valor DiffTime subyacente?

b) ¿Cómo convierto un DiffTime en un número entero con su valor en segundos? Hay una función secondsToDiffTime pero no pude encontrar su inversa.

Respuesta

15

¿Es posible desenvolver de alguna manera la IO y obtener el valor difftime subyacente?

Sí. Hay docenas de tutoriales en mónadas que explican cómo. Todos están basados ​​en la idea de que usted escribe una función que toma DiffTime y hace algo (por ejemplo, devolver IO()) o simplemente devuelve un Answer. Así que si usted tiene f :: DiffTime -> Answer, escribir

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

la que algunas personas prefieren escribir

time >>= (return . f) 

y si tiene continue :: DiffTime -> IO() tiene

time >>= continue 

O si lo prefiere, do notación:

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

Para obtener más información, consulte uno de los muchos tutorals en mónadas.

+0

Creo que es por simplicidad, especialmente para un principiante , podrías omitir el paréntesis a cambio. f y ¿cómo la sintaxis de estilo de espacio en blanco? – codebliss

+4

@codebliss: para un principiante quería hacer las cosas muy explícitas y por lo tanto no exigir que el lector entienda los detalles de la precedencia o el diseño del operador –

+1

También puede hacer 'f <$> time' ya que cada mónada es un functor. IMO esto se ve muy bien. –

7

a) Por supuesto, es posible obtener el valor DiffTime; de lo contrario, esta función sería bastante inútil. Tendrá que leer sobre las mónadas. This chapter y the next de Real World Haskell tiene una buena introducción.

b) El docs for DiffTime dice que es una instancia de la clase Real, es decir, se puede tratar como un número real, en este caso, el número de segundos. Convirtiéndola en segundos es, pues, una simple cuestión de encadenamiento de las funciones de conversión:

diffTimeToSeconds :: DiffTime -> Integer 
diffTimeToSeconds = floor . toRational 
+0

Sin embargo, pierde los picosegundos de esta manera. Por lo general, '' truncado. (de precisión integral *). toRational. utctDayTime', que te da el número de picosegundos. (Y para sembrar un RNG, el uso de este valor le permite tener más de un estado inicial por segundo, lo que es importante en muchas aplicaciones). – jrockway

+0

(ah, y precisión = 10000000000000) – jrockway

7

Si está planeando usar el módulo estándar System.Random para la generación de números aleatorios, entonces ya hay un generador con una inicialización dependiente del tiempo inicializado para usted: puede obtenerlo llamando al getStdGen :: IO StdGen. (Por supuesto, todavía necesita la respuesta a la parte (a) de su pregunta para usar el resultado.)

0

Esta función no es exactamente lo que pide el OP. Pero es útil:

λ: import Data.Time.Clock 
λ: let getSeconds = getCurrentTime >>= return . fromRational . toRational . utctDayTime 
λ: :i getSeconds 
getSeconds :: IO Double  -- Defined at <interactive>:56:5 
λ: getSeconds 
57577.607162 
λ: getSeconds 
57578.902397 
λ: getSeconds 
57580.387334 
Cuestiones relacionadas