-
- open Batteries
-
- module type N = sig
- type t
- val make: unit -> t
- val add_to_self: t -> t -> unit
- val as_float: t -> float
- end
-
- module Int: N = struct
- type t = int ref
- let make () = ref 1
- let add_to_self x y = x := !x + !y
- let as_float = (!) |- float_of_int
- end
-
- module Float: N = struct
- type t = float ref
- let make () = ref 0.5
- let add_to_self x y = x := !x +. !y
- let as_float = (!)
- end
-
- let which_module = function
- | "float" -> (module Float: N)
- | "int" -> (module Int: N)
- | _ -> invalid_arg "which_module"
-
- let parse: string -> (module N with type t = 'a) * 'a = fun (type a) s ->
- let module C = (val (which_module s): N) in
- (module C: N), C.make ()
-
- let do_repetitive_work: (module N with type t = 'a) -> 'a -> 'a = fun (type a) m (x: a) ->
- let module C = (val m: N with type t = a) in
- let y = C.make ();
- C.add_to_self y x;
- C.add_to_self y (C.make ());
- y
-
- let () = if !Sys.interactive then () else
- let m, x = parse Sys.argv.(1) in
- let module C = (val m: N) in
- do_repetitive_work (module C: N with type t = C.t) x
- |> C.as_float
- |> Printf.printf "%g\n"
-