This site is updated infrequently. For up-to-date information, please visit the new OCaml website at ocaml.org.

ambitious proposal: polymorphic arithmetics
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
 Date: 2005-04-07 (01:58) From: Jacques Garrigue Subject: Re: [Caml-list] ambitious proposal: polymorphic arithmetics
```From: William Lovas <wlovas@stwing.upenn.edu>

> > Yes, polymorphic comparison already breaks type abstraction.
>
> I did not realize this!  Can somebody explain the following interactions?
>
>     # let r = Ratio.ratio_of_int 5;;
>     val r : Ratio.ratio = <abstr>
>     # r = r;;
>     Exception: Invalid_argument "equal: abstract value".
>
>     # module M : sig type t;; val of_int : int -> t end =
>         struct type t = int;; let of_int x = x end;;
>         module M : sig type t val of_int : int -> t end
>     # let t = M.of_int 5;;
>     val t : M.t = <abstr>
>     # t = t;;
>     - : bool = true
>
> I thought that perhaps all comparisons of abstract values resulted in a
> runtime error, but evidently i was mistaken :/  What's the secret to making
> a type "really" abstract?

The error message is a bit misleading: it actually means an internal
object with abstract tag. You can only produce those on the C side.
However, this gives you a trick if you want to protect a type from
comparisons: include an incomparable field in it. Better to put it as
first field, as it then makes sure that even ordering cannot be be
checked.

type 'a protected = {prot: unit Weak.t; desc: 'a}
let protect d = {prot = Weak.create 1; desc = d }

Now protected values are impossible to compare.
More precisely, they are only comparable when physically equal, which
you can anyway check with ==. Even in this case polymorphic equality
will fail (it checks even physically equal values.)

# let x = protect 1;;
val x : int protected = {prot = <abstr>; desc = 1}
# x=x;;
Exception: Invalid_argument "equal: abstract value".
# compare x x;;
- : int = 0
# let y = protect 1;;
val y : int protected = {prot = <abstr>; desc = 1}
# compare x y;;
Exception: Invalid_argument "equal: abstract value".

So, if you really need abstraction, you can have it.
(You can still break it using the Obj module, but this is another
story...)

Jacques Garrigue

```