Linear random number generator

Lazy-evaluation based linear streams is a very useful feature
in ATS. At this point, I think it is also a unique feature in ATS.
I give as follows a stream-based implementation of a linear random
number generator:

(*
** Linear random number generator
)
(
****** ****** )
//
// How to test:
// ./randerlin
// valgrind ./randerlin
//
// How to compile:
// patscc -DATS_MEMALLOC_LIBC -o randerlin randerlin.dats
//
(
****** ****** )
//
#include
"share/atspre_staload.hats"
//
(
****** ****** *)

datavtype
rander = RANDER of stream_vt (ulint)

(* ****** ****** *)

extern
fun
rander (!rander): ulint

(* ****** ****** *)

extern
fun rander_make (): rander
extern
fun rander_free (r: rander): void
overload ~ with rander_free

(* ****** ****** *)

implement
rander ® = let
//
val+@RANDER (xs) = r
val-~stream_vt_cons (x, xs2) = !xs
val () = xs := xs2
prval () = fold@ ®
//
in
x
end // end of [rander]

(* ****** ****** *)

implement
rander_make () = let
//
fun aux
(
state: ulint
) : stream_vt (ulint) = $ldelay
(
//
let
//
val state =
(state * 196314165UL) + 907633515UL
//
in
stream_vt_cons (state, aux (state))
end
//
) (* end of [$ldelay] *) // end of [val]
//
in
RANDER (aux (31435926536UL(init)))
end // end of [rander_make]

(* ****** ****** *)

implement
rander_free ® = let val~RANDER(xs) = r in ~xs end

(* ****** ****** *)

implement
main0 () =
{
//
val r0 = rander_make ()
//
val () = println! ("rander(r0) = ", rander(r0))
val () = println! ("rander(r0) = ", rander(r0))
val () = println! ("rander(r0) = ", rander(r0))
//
val () = ~r0 // freeing the random number generator
//
} (* end of [main0] *)

(* ****** ****** *)

(* end of [randerlin.dats] *)

The code can also be found here: