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:というかいつ失敗するんだろうか?