Pergunta

Estou precisando de alguns Ints 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.

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top