Browse thread
[Caml-list] const equivalent for mutable types?
-
Christopher A. Gorski
- Jean-Marie Gaillourdert
- Markus Mottl
- Brian Hurt
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ 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