Browse thread
ambitious proposal: polymorphic arithmetics
[
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: | 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