Как получить системное время в Haskell с помощью Data.Time.Clock?

Мне нужно немного Int использовать для генерации семян для случайных чисел, поэтому я хотел использовать старый трюк использования системного времени в качестве семени.

Итак, я попытался использовать пакет Data.Time, и мне удалось сделать следующее:

import Data.Time.Clock

time = getCurrentTime >>= return . utctDayTime

Когда я запускаю время, я получаю такие вещи, как:

Prelude Data.Time.Clock> time
55712.00536s

Тип time - IO DiffTime. Я ожидал увидеть тип IO Something, поскольку это зависит от вещей, внешних по отношению к программе. Поэтому у меня есть два вопроса:

a) Можно ли каким-то образом развернуть IO и получить базовое значение DiffTime?

b) Как преобразовать DiffTime в целое число с его значением в секундах? Там функция secondsToDiffTime, но я не мог найти ее обратную.

Ответ 1

Можно ли как-то развернуть IO и получить базовое значение DiffTime?

Да. Есть несколько уроков по монадам, которые объясняют, как это сделать. Все они основаны на идее, что вы пишете функцию, которая принимает DiffTime и что-то делает (скажем, возврат IO ()) или просто возвращает Answer. Поэтому, если у вас есть f :: DiffTime -> Answer, вы пишете

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

который некоторые люди предпочитают писать

time >>= (return . f) 

и если у вас есть continue :: DiffTime -> IO (), у вас есть

time >>= continue

Или вы можете предпочесть обозначение do:

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

Более подробно проконсультируйтесь с одним из многих прекрасных учителей на монадах.

Ответ 2

a) Конечно, можно получить значение DiffTime; в противном случае эта функция была бы совершенно бессмысленной. Вам нужно будет прочитать о монадах. В этой главе и в следующем Real World Haskell есть хорошая введение.

b) docs для DiffTime говорят, что это экземпляр класса Real, то есть он может рассматриваться как реальный число, в этом случае количество секунд. Таким образом, преобразование его в считанные секунды является простым способом цепочки преобразования:

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

Ответ 3

Если вы планируете использовать стандартный модуль System.Random для генерации случайных чисел, то для вас уже есть генератор с инициализированным по времени семенами: вы можете получить его, вызвав getStdGen :: IO StdGen. (Конечно, вам все равно нужен ответ на часть (а) вашего вопроса, чтобы использовать результат.)

Ответ 4

Эта функция не совсем то, что спрашивает OP. Но это полезно:

λ: 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