Refnum
Stephen Weeks
MLton@sourcelight.com
Thu, 20 Sep 2001 10:20:58 -0700
> re Norman's thing, isn't it relatively clear that his original signature
> isn't achievable without cheats like cast? It would require some kind of
> type dispatch since given a 'a ref you can only compare it to other 'a refs.
It's pretty clear, but I'm not totally sure. For example, here is an
implementation of Norman's original signature with a slightly different
underlying implementation of refs.
structure Refnum:
sig
structure Ref:
sig
type 'a t
val reff: 'a -> 'a t
val ! : 'a t -> 'a
val := : 'a t * 'a -> unit
end
val refnum: 'a Ref.t -> int
end =
struct
structure Ref =
struct
datatype 'a t = T of 'a option ref
fun reset (T r) () =
case !r of
NONE => raise Fail "Ref.reset bug"
| SOME v => (r := NONE; fn () => r := SOME v)
val isSome = fn (T r) => isSome (! r)
fun reff x = T (ref (SOME x))
val ! = fn (T r) => valOf (! r)
val op := = fn (T r, v) => r := SOME v
end
val count: int ref = ref 0
val refs: (unit -> unit -> unit) list ref = ref []
fun 'a refnum (r: 'a Ref.t) =
let
fun loop (l, n) : int =
case l of
[] =>
let
val n = !count + 1
in
count := n
; refs := Ref.reset r :: !refs
; n
end
| f :: l =>
let
val f = f ()
val is = Ref.isSome r
val _ = f ()
in
if is
then loop (l, n - 1)
else n
end
in
loop (!refs, !count)
end
end