MLton用乱数モジュール

以前SML/NJ用で乱数を使うために,MoscowMLの乱数モジュールを真似たモノを作りました.
今回はMLton用に同じシグネチャを持つモジュールを定義しました.

シグネチャはMoscowMLの提供するモノと同じ.

signature MOSCOWRANDOM =
sig
  type generator
  val newgenseed : real -> generator
  val newgen     : unit -> generator
  val random     : generator -> real
  val randomlist : int * generator -> real list
  val range      : int * int -> generator -> int
  val rangelist  : int * int -> int * generator -> int list
end

MLtonによる実装.

structure MoscowRandom :> MOSCOWRANDOM =
struct
  type generator = Word.word
  structure R = MLton.Random

  fun newgen () = case R.useed () of
                       SOME r => r
                     | NONE   => R.rand ()
  fun newgenseed r = (R.srand (Word.fromInt (Real.toInt IEEEReal.TO_NEAREST r)); newgen ())
  fun random ctx = let
    val x =   (Real.fromLargeInt (Word.toLargeInt ctx))
            / (Real.fromLargeInt (Word.toLargeInt (Word.notb (Word.fromInt 0))))
  in x end

  fun randomlist (n,seed) : real list = let
    val _ = R.srand seed
    val (_,xs) = List.foldr (fn(_,(r,xs))=> (R.rand(),random r::xs))
                    (R.rand(),[]) (List.tabulate(n,fn _=>0.0))
  in xs
  end
  fun range (f,t) seed =
  let val x = (Real.fromInt f + Real.fromInt (t-f) * (random seed))
  in
    Real.toInt IEEEReal.TO_NEAREST x
  end
  fun rangelist (f,t) (n,seed) : int list =
  let
    val _ = R.srand seed
    val (_,xs) = List.foldr (fn(_,(s,xs))=>(R.rand(),range (f,t) s::xs))
                    (R.rand(),[]) (List.tabulate(n,fn _=>0))
  in xs end
end

structure R = MoscowRandom;
fun println s = print (s^"\n");
val _ = println(String.concatWith ","
                (map Int.toString  (R.rangelist (0,10) (10,R.newgen()))));

一番下はサンプルコードです. これを実行すると,

$ cat mlton_random.mlb
local
	$(SML_LIB)/basis/basis.mlb
	$(SML_LIB)/basis/mlton.mlb
	mlton_random.sml
in
	structure MoscowRandom
end
$ mlton mlton_random.mlb && ./mlton_random
1,0,10,1,3,7,1,4,7,10

こんな感じ.


実装は怪しげですが,まあそれっぽい数字が出ているのでヨシとします.
ところで MLton.Random.seed:unit -> word option は見ての通り失敗する可能性がありますが,
失敗したとしたらどうすればいいのやら…(^^;; *1


ともあれこれでSML/NJとMLtonで同じ乱数モジュールが使えるようになりました.

*1:というかいつ失敗するんだろうか?