Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] const equivalent for mutable types?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Markus Mottl <markus@o...>
Subject: Re: [Caml-list] const equivalent for mutable types?
On Sat, 31 Jul 2004, Christopher A. Gorski wrote:
> In my code I find that I'm passing a lot of mutable values to functions. 
>  Some functions merely read the values.  Others modify the values.  Is 
> there a method in OCaml for reproducing behavior similar in spirit to 
> the const declaration in C?

No, you'd need an abstract module for this to hide the concrete
representation.  This is actually good SE-practice.

You can do this very conveniently using so-called phantom types.  For the
special case of references, here is an example that implements ones,
which can be made constant:

---------------------------------------------------------------------------
module type REF = sig
  type ('a, 'rw) t

  val ref : 'a -> ('a, [ `R | `W ]) t
  val (!) : ('a, [> `R ]) t -> 'a
  val (:=) : ('a, [> `W ]) t -> 'a -> unit

  val incr : (int, [> `W ]) t -> unit
  val decr : (int, [> `W ]) t -> unit

  external const : ('a, [> `R ]) t -> ('a, [ `R ]) t = "%identity"
  external normal_ref : ('a, [ `R | `W ]) t -> 'a ref = "%identity"
end

module Ref : REF = struct
  type ('a, 'rw) t = 'a ref

  let ref = ref
  let (!) = (!)
  let (:=) = (:=)

  let incr = incr
  let decr = decr

  external const : ('a, [> `R ]) t -> ('a, [ `R ]) t = "%identity"
  external normal_ref : ('a, [ `R | `W ]) t -> 'a ref = "%identity"
end
---------------------------------------------------------------------------

The phantom variable is 'rw.  When creating references, it can be any
of `R (for reading) and `T (for writing).  Some functions only require
the reference to be readable (like (!)), others only need to write to
them (e.g. (:=)).  References are made constant by simply applying the
(internal) identity function to them, which is actually a no-op.  But we
only leave the `R-flag in the type.  A "normal" reference can be made
from the upper ones only if they support both reading and writing.

> let result = change (const r)
> 
> and have the compiler give me a type error.

Now we try this out with your example:

---------------------------------------------------------------------------
open Ref

let () =
  let t = ref 0 in
  let change r = incr r in
  let nochange r = Printf.printf "test:%d\n" !r in
  change (const t)
---------------------------------------------------------------------------

And we get:

  This expression has type (int, [ `R ]) Ref.t but is here used with type
    (int, [> `W ]) Ref.t

"nochange" will work without a type error as expected.

Regards,
Markus

-- 
Markus Mottl          http://www.oefai.at/~markus          markus@oefai.at

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners