Search code examples
datetimesmlrandom-seed

SML Date structure


I've been trying to figure out random number generation in SML. There's a standard library function that requires a fresh seed for each calculation

let
    val seed = Random.rand (123,456)
in
    List.tabulate(5, fn i => Random.randRange (1,100)  seed)
end

val it = [26,39,64,39,84] : int list

This works fine, but unless you update the seed with a new number pair each time, you get back the same random numbers. One way to get new numbers was found here, but this seems out of date, i.e., it doesn't seem to work -- or I'm just not using it correctly.

val seed = 
    let
        val Date.DATE(d) = Date.fromTime(Time.now())
        val m            = #minute d
        val s            = #second d
    in
        m,s)
    end

fun random (l,h) = Random.randRange (l,h) seed

Specifically, I can't get the

val Date.DATE(d) = Date.fromTime(Time.now())

to work. I've tried

- val Date.DATE(d) = Date.fromTimeLocal(Time.now());

but I get the error

stdIn:7392.1-7392.10 Error: unbound variable or constructor: DATE in path Date.DATE
stdIn:7392.1-7392.10 Error: variable found where constructor is required: Date.DATE
stdIn:7392.1-7392.12 Error: constant constructor applied to argument in pattern:bogus

This, however, works

- val mydate = Date.fromTimeLocal(Time.now())
val mydate =
:   DATE
:     {day=17,hour=22,isDst=SOME true,minute=27,month=Apr,
:      offset=SOME (TIME {usec=#}),second=3,wday=Fri,yday=107,year=2020}
:   : Date.date

but as a beginner, I don't really know how to extract anything from mydate. It seems the Date.DATE(d) = is supposed to "cast" the evaluation into the variable d which can be accessed by the record fields #minute and #second... Some explanation would be greatly appreciated. (Here is the Date structure.)


Solution

  • The FAQ is very out of date and seems to use a really old Date structure.

    This works for me:

    val seed = 
        let
            val d = Date.fromTimeLocal(Time.now())
            val m = Date.minute d
            val s = Date.second d
        in
            Random.rand (m,s)
        end;
    
    fun random (l,h) = Random.randRange (l,h) seed;
    

    Test:

    - random (1,10);
    val it = 7 : int
    - random (1,10);
    val it = 8 : int
    - random (1,10);
    val it = 7 : int
    - random (1,10);
    val it = 4 : int
    - random (1,10);
    val it = 3 : int