caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Strange physical equality behavior
@ 2003-11-09 18:34 Oleg Trott
  2003-11-10  1:33 ` Jacques Garrigue
  0 siblings, 1 reply; 10+ messages in thread
From: Oleg Trott @ 2003-11-09 18:34 UTC (permalink / raw)
  To: caml-list

        Objective Caml version 3.07+2

# sin == sin;;
- : bool = false
# let f = sin;;
val f : float -> float = <fun>
# f == f;;
- : bool = true

I don't like the fact that (sin == sin) returns false.

-- 
Oleg Trott <oleg_trott@columbia.edu>

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-09 18:34 [Caml-list] Strange physical equality behavior Oleg Trott
@ 2003-11-10  1:33 ` Jacques Garrigue
  2003-11-10  2:25   ` Oleg Trott
  2003-11-11  6:48   ` Oleg Trott
  0 siblings, 2 replies; 10+ messages in thread
From: Jacques Garrigue @ 2003-11-10  1:33 UTC (permalink / raw)
  To: oleg_trott; +Cc: caml-list

From: Oleg Trott <oleg_trott@columbia.edu>

>         Objective Caml version 3.07+2
> 
> # sin == sin;;
> - : bool = false
> # let f = sin;;
> val f : float -> float = <fun>
> # f == f;;
> - : bool = true
> 
> I don't like the fact that (sin == sin) returns false.

This is coherent with the specification of (==), which says that
it is fully specified only for mutable structures.
(** [e1 == e2] tests for physical equality of [e1] and [e2].
   On integers and characters, physical equality is identical to structural
   equality. On mutable structures, [e1 == e2] is true if and only if
   physical modification of [e1] also affects [e2].
   On non-mutable structures, the behavior of [(==)] is
   implementation-dependent; however, it is guaranteed that
   [e1 == e2] implies [e1 = e2]. *)
And note that:
  # sin = sin;;
  Exception: Invalid_argument "equal: functional value".
so returning false in this case is valid.

This is for the defensive part.

Now the real explanation: primitives (appearing as "external" in the
.mli) are not closures by themselves. A closure is built as needed.
As a result, two different occurences of "sin" will create different
closures.
If this is a problem for you, you should just be careful of wrapping
all your primitives. This is just what "let f = sin" does.
(Note however that the specification doesn't say what should be (==)
for closures either. It just happens to be reflexive in the current
implementation.)

Jacques Garrigue

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-10  1:33 ` Jacques Garrigue
@ 2003-11-10  2:25   ` Oleg Trott
  2003-11-10  8:29     ` Jacques Garrigue
  2003-11-11  6:48   ` Oleg Trott
  1 sibling, 1 reply; 10+ messages in thread
From: Oleg Trott @ 2003-11-10  2:25 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

On Sunday 09 November 2003 08:33 pm, Jacques Garrigue wrote:
> From: Oleg Trott <oleg_trott@columbia.edu>
>
> >         Objective Caml version 3.07+2
> >
> > # sin == sin;;
> > - : bool = false
> > # let f = sin;;
> > val f : float -> float = <fun>
> > # f == f;;
> > - : bool = true
> >
> > I don't like the fact that (sin == sin) returns false.
>
> This is coherent with the specification of (==), which says that
> it is fully specified only for mutable structures.
> (** [e1 == e2] tests for physical equality of [e1] and [e2].
>    On integers and characters, physical equality is identical to structural
>    equality. On mutable structures, [e1 == e2] is true if and only if
>    physical modification of [e1] also affects [e2].
>    On non-mutable structures, the behavior of [(==)] is
>    implementation-dependent; however, it is guaranteed that
>    [e1 == e2] implies [e1 = e2]. *)

<snip>

So returning "true" for "sin == sin" and "sin = sin" wouldn't break the above 
guarantee.

Here are my reasons for wanting such behavior (not just for "sin" of course, 
but also "(+)" , etc., and especially for "compare"):

As was discussed lately [1], the functorial interfaces (as used in the 
standard library) are somewhat clumsy. One solution could be to pass the 
necessary ordering and hashing functions as optional parameters to "emtpy" or 
"create". However, in this case, functions would need to be compared at 
runtime

compare_functions f g = try f = g with _ -> false

So e.g. "compare == compare" returning true would be a lot more convenient

[1] http://groups.google.com/groups?selm=fa.cvslsk1.37iiq9%40ifi.uio.no


-- 
Oleg Trott <oleg_trott@columbia.edu>

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-10  2:25   ` Oleg Trott
@ 2003-11-10  8:29     ` Jacques Garrigue
  2003-11-10 18:41       ` Michal Moskal
  0 siblings, 1 reply; 10+ messages in thread
From: Jacques Garrigue @ 2003-11-10  8:29 UTC (permalink / raw)
  To: oleg_trott; +Cc: caml-list

From: Oleg Trott <oleg_trott@columbia.edu>

> So returning "true" for "sin == sin" and "sin = sin" wouldn't break
> the above guarantee.

Of course.
And returning true for "sin = (fun x -> cos (x -. acos (-1.) /. 2))"
wouldn't break it either.
The specification is just designed to avoid having to do that: to
allow the compiler to choose the most efficient runtime
representation. It might actually just return "false" when you compare
any two functions, but even this would require some more computation.

> Here are my reasons for wanting such behavior (not just for "sin" of course, 
> but also "(+)" , etc., and especially for "compare"):
> 
> As was discussed lately [1], the functorial interfaces (as used in the 
> standard library) are somewhat clumsy. One solution could be to pass the 
> necessary ordering and hashing functions as optional parameters to "emtpy" or 
> "create". However, in this case, functions would need to be compared at 
> runtime
> 
> compare_functions f g = try f = g with _ -> false
> 
> So e.g. "compare == compare" returning true would be a lot more convenient

The problem is that compare has several implementations, depending on
the type of its argument, to be more efficient. One may imagine tricks
to make sure that any one of these implementations is shared between
all its occurences (but even this may be complicated while keeping
inlining). But generic compare cannot be equal to float compare, while
they are just separated by their types.

The functorial approach offers a much cleaner solution.
Alternatively, you can think of a system of registered comparison
functions:
  type 'a comparison = {id: int; compare: 'a -> 'a -> int}
  let count = ref 0
  let make_compare f = incr count; {id = !count; compare = f}
  let same f1 f2 = (f1.id = f2.id)
If comparison is kept abstract, you can then safely check for
equality.
A lighter way would be to combine this registration with the "empty"
function: two sets can be combined if they were created from the same
empty set.

The last solution is not to bother about that: I'm yet to see code
mixing two sets of the same type but with different comparison
functions. Sounds silly.

Jacques Garrigue

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-10  8:29     ` Jacques Garrigue
@ 2003-11-10 18:41       ` Michal Moskal
  2003-11-11  1:35         ` Jacques Garrigue
  0 siblings, 1 reply; 10+ messages in thread
From: Michal Moskal @ 2003-11-10 18:41 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: oleg_trott, caml-list

On Mon, Nov 10, 2003 at 05:29:24PM +0900, Jacques Garrigue wrote:
> The last solution is not to bother about that: I'm yet to see code
> mixing two sets of the same type but with different comparison
> functions. Sounds silly.

For me it doesn't. You cannot prevent user from shooting his foot in
this case. For example consider:

  let cmp x y = Random.int ()

This is very good comparision functions, and can also be used with
functiorial interface. You may say it is silly, but random functions 
(that are not total orderings) can be created by accident (for example
by comparing some mutable member or what's not).

-- 
: Michal Moskal :: http://www.kernel.pl/~malekith : GCS {C,UL}++++$ a? !tv
: PLD Linux ::::::::: Wroclaw University, CS Dept : {E-,w}-- {b++,e}>+++ h

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-10 18:41       ` Michal Moskal
@ 2003-11-11  1:35         ` Jacques Garrigue
  0 siblings, 0 replies; 10+ messages in thread
From: Jacques Garrigue @ 2003-11-11  1:35 UTC (permalink / raw)
  To: malekith; +Cc: caml-list

From: Michal Moskal <malekith@pld-linux.org>
> On Mon, Nov 10, 2003 at 05:29:24PM +0900, Jacques Garrigue wrote:
> > The last solution is not to bother about that: I'm yet to see code
> > mixing two sets of the same type but with different comparison
> > functions. Sounds silly.
> 
> For me it doesn't. You cannot prevent user from shooting his foot in
> this case. For example consider:
> 
>   let cmp x y = Random.int ()
> 
> This is very good comparision functions, and can also be used with
> functiorial interface. You may say it is silly, but random functions 
> (that are not total orderings) can be created by accident (for example
> by comparing some mutable member or what's not).

Looks like you are supporting my point.
I was just saying that I'm yet to see somebody trying to take the
union of two sets defined with different (supposedly correct)
comparison functions.
And you point out a much more probable danger, which cannot be
prevented neither by the type system or dynamic checks.
So using the type system (or dynamic checks) to prevent an unprobable
risk, while there are much more probable ones, seems an overkill.

But I won't go more in that direction: as a type freak, preventing any
risk is good.

     Jacques Garrigue

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-10  1:33 ` Jacques Garrigue
  2003-11-10  2:25   ` Oleg Trott
@ 2003-11-11  6:48   ` Oleg Trott
  2003-11-11 16:46     ` David Brown
  2003-11-11 17:08     ` brogoff
  1 sibling, 2 replies; 10+ messages in thread
From: Oleg Trott @ 2003-11-11  6:48 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

On Sunday 09 November 2003 08:33 pm, Jacques Garrigue wrote:
>  On mutable structures, [e1 == e2] is true if and only if
>    physical modification of [e1] also affects [e2].

By the way, either "mutable structures" or "physical modification" need to be 
clarified, because if (int ref list) is "mutable" then the above is wrong:

 let a = [ref 0];;
 let b = ref 0 :: a;;
 incr (List.hd a);; (*  physical  ? *)
 a == b;;
 b;;

> On non-mutable structures, the behavior of [(==)] is
> implementation-dependent; however, it is guaranteed that
> [e1 == e2] implies [e1 = e2].

This doesn't work for "nan" though, as was recently discussed. [1] 

> The functorial approach offers a much cleaner solution.

I'm not convinced.

With non-functorial sets:

type t = Leaf of string | Node of t Set.t

How would you do this with functorial sets? Perhaps like this:

http://groups.google.com/groups?selm=fa.dlqsupe.1c6ajga%40ifi.uio.no

    module A : sig
                 type t = Leaf of string | Node of ASet.t
                 val compare: t -> t -> int
               end
             = struct
                 type t = Leaf of string | Node of ASet.t
                 let compare t1 t2 =
                   match (t1, t2) with
                     (Leaf s1, Leaf s2) -> Pervasives.compare s1 s2
                   | (Leaf _, Node _) -> 1
                   | (Node _, Leaf _) -> -1
                   | (Node n1, Node n2) -> ASet.compare n1 n2
               end
    and ASet : Set.S with type elt = A.t
             = Set.Make(A)

(BTW, that example doesn't yet work in 3.07-2 default toplevel. And couldn't 
one write "let compare = Pervasives.compare" above? )

> I'm yet to see code mixing two sets of the same type but with different 
> comparison functions.

Exactly! That's why *statically* assuring ordering function consistency is not 
all that important [2]. Which is why x==x would be a bigger help than 
recursive modules.

[1] I can understand false "nan = nan", because "nan" is a kind of exception, 
but false "x == x" feels very non-mathematical to me.

[2] I am a static typing fan, but this seems excessive.

Regards,
Oleg

P.S. I've already participated in this discussion longer than my tolerance for 
language-lawyerism or passion about this issue allow me, so I'll probably end 
it here.
-- 
Oleg Trott <oleg_trott@columbia.edu>

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-11  6:48   ` Oleg Trott
@ 2003-11-11 16:46     ` David Brown
  2003-11-12  0:32       ` William Lovas
  2003-11-11 17:08     ` brogoff
  1 sibling, 1 reply; 10+ messages in thread
From: David Brown @ 2003-11-11 16:46 UTC (permalink / raw)
  To: Oleg Trott; +Cc: Jacques Garrigue, caml-list

On Tue, Nov 11, 2003 at 01:48:22AM -0500, Oleg Trott wrote:
> On Sunday 09 November 2003 08:33 pm, Jacques Garrigue wrote:
> >  On mutable structures, [e1 == e2] is true if and only if
> >    physical modification of [e1] also affects [e2].
> 
> By the way, either "mutable structures" or "physical modification" need to be 
> clarified, because if (int ref list) is "mutable" then the above is wrong:

If you take structure to mean a single data type, rather than a more
complicated data structure, then it is true.

Dave

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-11  6:48   ` Oleg Trott
  2003-11-11 16:46     ` David Brown
@ 2003-11-11 17:08     ` brogoff
  1 sibling, 0 replies; 10+ messages in thread
From: brogoff @ 2003-11-11 17:08 UTC (permalink / raw)
  To: Oleg Trott; +Cc: Jacques Garrigue, caml-list

On Tue, 11 Nov 2003, Oleg Trott wrote:
> On Sunday 09 November 2003 08:33 pm, Jacques Garrigue wrote:
> > The functorial approach offers a much cleaner solution.
>
> I'm not convinced.
>
> With non-functorial sets:
>
> type t = Leaf of string | Node of t Set.t
>
> How would you do this with functorial sets? Perhaps like this:
>
> http://groups.google.com/groups?selm=fa.dlqsupe.1c6ajga%40ifi.uio.no
>
>     module A : sig
>                  type t = Leaf of string | Node of ASet.t
>                  val compare: t -> t -> int
>                end
>              = struct
>                  type t = Leaf of string | Node of ASet.t
>                  let compare t1 t2 =
>                    match (t1, t2) with
>                      (Leaf s1, Leaf s2) -> Pervasives.compare s1 s2
>                    | (Leaf _, Node _) -> 1
>                    | (Node _, Leaf _) -> -1
>                    | (Node n1, Node n2) -> ASet.compare n1 n2
>                end
>     and ASet : Set.S with type elt = A.t
>              = Set.Make(A)
>
> (BTW, that example doesn't yet work in 3.07-2 default toplevel. And couldn't
> one write "let compare = Pervasives.compare" above? )

 module rec A : (* a forgotten "rec" inserted *)
    sig
      type t = Leaf of string | Node of ASet.t
      val compare: t -> t -> int
    end
    = struct
      type t = Leaf of string | Node of ASet.t
      let compare t1 t2 =
        match (t1, t2) with
          (Leaf s1, Leaf s2) -> Pervasives.compare s1 s2
        | (Leaf _, Node _) -> 1
        | (Node _, Leaf _) -> -1
        | (Node n1, Node n2) -> ASet.compare n1 n2
    end
and ASet : Set.S with type elt = A.t
      = Set.Make(A)

It's a simple syntax error. And, if we use Pervasives.compare, we don't know
for sure how the Leaf <-> Node comparison will work, do we? What if it's
dependent on the order of occurrence of those constructors in the type
definition?

Functors can be heavy, but I prefer that approach too. Having a bit of
recursiveness in the module language makes them much nicer. Now if we can
just get generics...

-- Brian


-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Caml-list] Strange physical equality behavior
  2003-11-11 16:46     ` David Brown
@ 2003-11-12  0:32       ` William Lovas
  0 siblings, 0 replies; 10+ messages in thread
From: William Lovas @ 2003-11-12  0:32 UTC (permalink / raw)
  To: caml-list

On Tue, Nov 11, 2003 at 08:46:56AM -0800, David Brown wrote:
> On Tue, Nov 11, 2003 at 01:48:22AM -0500, Oleg Trott wrote:
> > On Sunday 09 November 2003 08:33 pm, Jacques Garrigue wrote:
> > >  On mutable structures, [e1 == e2] is true if and only if
> > >    physical modification of [e1] also affects [e2].
> > 
> > By the way, either "mutable structures" or "physical modification" need
> > to be clarified, because if (int ref list) is "mutable" then the above
> > is wrong:
> 
> If you take structure to mean a single data type, rather than a more
> complicated data structure, then it is true.

Well, what do you mean by "a single data type", then?  Surely a record is a
single data type, but ...

    type r = { mutable a: int; mutable r: r }

    let rec r1 = { a = 5; r = r2 }
        and r2 = { a = 7; r = r1 }

Surely you wouldn't argue that this is an immutable data structure, either
-- it contains nothing *but* mutable fields!  And yet,

    r1.a <- 6

also "affects" r2, but r1 != r2.  (Admittedly, though, the ambiguity may
lie in the usage of the word "affects".)

*shrug* Maybe it's a bit contrived, but i would err on the side of caution
and say that the documentation should be made clearer.

William

-------------------
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


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-11-12  0:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-09 18:34 [Caml-list] Strange physical equality behavior Oleg Trott
2003-11-10  1:33 ` Jacques Garrigue
2003-11-10  2:25   ` Oleg Trott
2003-11-10  8:29     ` Jacques Garrigue
2003-11-10 18:41       ` Michal Moskal
2003-11-11  1:35         ` Jacques Garrigue
2003-11-11  6:48   ` Oleg Trott
2003-11-11 16:46     ` David Brown
2003-11-12  0:32       ` William Lovas
2003-11-11 17:08     ` brogoff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).