Como obter o tempo do sistema em haskell usando data.time.clock?
-
22-09-2019 - |
Pergunta
Estou precisando de alguns Int
s Para usar como semente para geração de números aleatórios e, portanto, eu queria usar o antigo truque de usar o tempo do sistema como semente.
Então eu tentei usar o pacote Data.time e consegui fazer o seguinte:
import Data.Time.Clock
time = getCurrentTime >>= return . utctDayTime
Quando eu corro o tempo, entendo as coisas:
Prelude Data.Time.Clock> time
55712.00536s
O tipo de time
é IO DiffTime
. Eu esperava ver um IO Something
Digite como isso depende de coisas externas para o programa. Então, eu tenho duas perguntas:
a) É possível desembrulhar de alguma forma o IO e obter o valor diferente subjacente?
b) Como converto um diferença em um número inteiro com seu valor em segundos? Há uma função secondsToDiffTime
Mas não consegui encontrar o seu inverso.
Solução
De alguma forma, é possível desembrulhar o IO e obter o valor diferente subjacente?
Sim. Existem dezenas de tutoriais em Mônadas que explicam como. Todos eles são baseados na ideia de que você escreve um função isso leva DiffTime
e faz algo (digamos retornando IO ()
) ou apenas retorna um Answer
. Então, se você tiver f :: DiffTime -> Answer
, você escreve
time >>= \t -> return (f t)
que algumas pessoas preferem escrever
time >>= (return . f)
E se você tiver continue :: DiffTime -> IO ()
Você tem
time >>= continue
Ou você pode preferir do
notação:
do { t <- time
; continue t -- or possibly return (f t)
}
Para mais informações, consulte um dos muitos bons tutores em Mônadas.
Outras dicas
a) É claro que é possível obter o DiffTime
valor; Caso contrário, essa função seria inútil. Você precisará ler em Mônadas. Este capítulo e nas próximas do mundo real Haskell tem uma boa introdução.
b) o documentos para DiffTime
diga que é uma instância do Real
Classe, ou seja, pode ser tratada como um número real, neste caso o número de segundos. Convertê -lo em segundos é, portanto, uma simples questão de encadear funções de conversão:
diffTimeToSeconds :: DiffTime -> Integer
diffTimeToSeconds = floor . toRational
Se você está planejando usar o padrão System.Random
Módulo para geração de números aleatórios, já existe um gerador com uma semente dependente do tempo inicializada para você: você pode obtê-lo ligando para ligar getStdGen :: IO StdGen
. (É claro que você ainda precisa da resposta para a parte (a) da sua pergunta para usar o resultado.)
Esta função não é exatamente o que o OP pergunta. Mas é ú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