Search code examples
recursionsmlml

SML returns the same tuples


I'm currently learning Standard ML, just for fun; What I'm trying to do is generate a list of 3-tuples of random ints between 1 and 100. My code:

fun reload() = use "filtertest.sml";

fun getSeed() = 
  LargeInt.toInt(Time.toMicroseconds(Time.now()) mod 1000);

fun fastpower(x, 0) = 1
  | fastpower(x, n) = 
      if n mod 2 = 0 then 
        fastpower(x*x, n div 2)
      else 
        x * fastpower(x*x, n div 2);

fun getRand(seed) = 
  let
    val m = 256
    val a = 11035
    val c = 12345
  in
    (a * seed + c) mod m
  end;

fun getRandTup() = 
  let
    val a = getRand(getSeed())
    val b = getRand(a)
    val c = getRand(b)
  in
    (a, b, c)
  end;

fun sumTup(x: int, y: int, z: int) = x + y + z;

fun getFromLast(lastTup) = 
  let
    val a = getRand(sumTup(lastTup))
    val b = getRand(a)
    val c = getRand(b)
  in
    (a, b, c)
  end;

fun genTupsHelper(0, tupList) = tupList
  | genTupsHelper(n, []) = 
      genTupsHelper(n-1, getRandTup() :: [])
  | genTupsHelper(n, tupList) = 
      getFromLast(hd tupList) :: genTupsHelper(n-1, tupList);

fun genTups(n) =
  genTupsHelper(n, []);

However, when I evaluate

genTups(10) 

My output is:

- genTups(10);
val it =
  [(243,218,55),(243,218,55),(243,218,55),(243,218,55),(243,218,55),
   (243,218,55),(243,218,55),(243,218,55),(243,218,55),(85,48,73)]
  : (int * int * int) list

I don't quite understand what I'm doing wrong here. Any help would be greatly appreciated.


Solution

  • Suggestion: use the Random structure.

    val r = Random.rand();
    
    fun getRand(a, b) =
      Random.randRange (a, b) r;
    
    fun getTuple(a, b) =
      (getRand(a, b), getRand(a, b), getRand(a, b));
    
    getTuple(0, 100);
    (* (2, 9, 97) *)
    

    Now, let's write a listInit function that creates a list of n length using the results of calling a function.

    fun listInit(n, f) =
      let
        fun aux(s, e, f, acc) =
          if s >= e then List.rev acc
          else aux(s+1, e, f, f s :: acc)
      in
        aux(0, n, f, [])
      end;
    

    For instance:

    listInit(3, (fn i => i));
    (* [0, 1, 2] *)
    

    We could also use this to generate a list of five random tuples.

    listInit(5, (fn _ => getTuple(0, 100)));
    (* [(10, 26, 31), (94, 46, 38), (7, 46, 89), 
        (92, 75, 61), (14, 60, 88)] *)