Version française
Home     About     Download     Resources     Contact us    
Browse thread
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: -- (:)
From: Jacques Garrigue <garrigue@m...>
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