caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Comparing variant types
@ 2011-04-28 19:16 Ethan Burns
  2011-04-28 21:07 ` Vincent Aravantinos
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Ethan Burns @ 2011-04-28 19:16 UTC (permalink / raw)
  To: caml-list

Hi,

I have a program that uses variant types as an enumeration.  While
profiling, I noticed that compare_val was being called a bunch.  When
I went to inspect why this was the case, it turns out that it was
being called to compare equality of my variants.  I am a bit confused,
however, because my understanding was that variants that are declared
without an 'of' clause were just represented as integers and therefore
a type containing only these simple elements should be directly
comparable (no compare_val).

While looking further into this, I found a little example where the
compiler seems to produce a simple comparison in one case and not in
another:

type dir = Left | Right | Up | Down | No_op

(* performs a simple comparison *)
let f a = a <> Right

(* calls out to C to do compare_val *)
let g (a:dir) b = a <> b

There is the -dlambda output:

(seq
  (let (f/69 (function a/70 (!= a/70 1a)))
    (setfield_imm 0 (global Test!) f/69))
  (let (g/71 (function a/72 b/73 (caml_notequal a/72 b/73)))
    (setfield_imm 1 (global Test!) g/71))
  0a)

Since both functions know that the types of the elements being compare
is 'dir', which contains only simple elements, why does the g function
still use compare_val?  Does the compiler not perform this particular
optimization?


Best,
Ethan

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

* Re: [Caml-list] Comparing variant types
  2011-04-28 19:16 [Caml-list] Comparing variant types Ethan Burns
@ 2011-04-28 21:07 ` Vincent Aravantinos
  2011-04-28 22:56   ` Ethan Burns
       [not found]   ` <354087020.772283.1304031467793.JavaMail.root@zmbs4.inria.fr>
  2011-04-29  8:57 ` Dmitry Bely
       [not found] ` <164004794.892685.1304067487325.JavaMail.root@zmbs2.inria.fr>
  2 siblings, 2 replies; 16+ messages in thread
From: Vincent Aravantinos @ 2011-04-28 21:07 UTC (permalink / raw)
  To: Ethan Burns; +Cc: caml-list

Hi,

without entering any details, probably the following links would be  
interesting to you:

http://ocaml.janestreet.com/?q=node/33
http://ocaml.janestreet.com/?q=node/35

V.

Le 28 avr. 11 à 21:16, Ethan Burns a écrit :

> Hi,
>
> I have a program that uses variant types as an enumeration.  While
> profiling, I noticed that compare_val was being called a bunch.  When
> I went to inspect why this was the case, it turns out that it was
> being called to compare equality of my variants.  I am a bit confused,
> however, because my understanding was that variants that are declared
> without an 'of' clause were just represented as integers and therefore
> a type containing only these simple elements should be directly
> comparable (no compare_val).
>
> While looking further into this, I found a little example where the
> compiler seems to produce a simple comparison in one case and not in
> another:
>
> type dir = Left | Right | Up | Down | No_op
>
> (* performs a simple comparison *)
> let f a = a <> Right
>
> (* calls out to C to do compare_val *)
> let g (a:dir) b = a <> b
>
> There is the -dlambda output:
>
> (seq
>  (let (f/69 (function a/70 (!= a/70 1a)))
>    (setfield_imm 0 (global Test!) f/69))
>  (let (g/71 (function a/72 b/73 (caml_notequal a/72 b/73)))
>    (setfield_imm 1 (global Test!) g/71))
>  0a)
>
> Since both functions know that the types of the elements being compare
> is 'dir', which contains only simple elements, why does the g function
> still use compare_val?  Does the compiler not perform this particular
> optimization?
>
>
> Best,
> Ethan
>
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>



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

* Re: [Caml-list] Comparing variant types
  2011-04-28 21:07 ` Vincent Aravantinos
@ 2011-04-28 22:56   ` Ethan Burns
       [not found]   ` <354087020.772283.1304031467793.JavaMail.root@zmbs4.inria.fr>
  1 sibling, 0 replies; 16+ messages in thread
From: Ethan Burns @ 2011-04-28 22:56 UTC (permalink / raw)
  To: Vincent Aravantinos; +Cc: caml-list

On Thu, Apr 28, 2011 at 5:07 PM, Vincent Aravantinos
<vincent.aravantinos@gmail.com> wrote:
> Hi,
>
> without entering any details, probably the following links would be
> interesting to you:
>
> http://ocaml.janestreet.com/?q=node/33
> http://ocaml.janestreet.com/?q=node/35

Thanks for the links.  Actually, I think that understand OCaml's
polymorphic comparison and how to get rid of it (for the most part). I
guess that I just found it surprising that the compiler doesn't seem
to optimize it away in this case (a variant type used as an
enumeration with only simple constructors).  I suppose that one
solution would be to just use let-bindings to associate integers with
names "by hand" instead of using the variant type.  I don't really
like that approach too much, however.


Ethan

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

* Re: [Caml-list] Comparing variant types
       [not found]   ` <354087020.772283.1304031467793.JavaMail.root@zmbs4.inria.fr>
@ 2011-04-29  8:46     ` Fabrice Le Fessant
  0 siblings, 0 replies; 16+ messages in thread
From: Fabrice Le Fessant @ 2011-04-29  8:46 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

On 04/29/2011 12:57 AM, Ethan Burns wrote:
> Thanks for the links.  Actually, I think that understand OCaml's
> polymorphic comparison and how to get rid of it (for the most part). I
> guess that I just found it surprising that the compiler doesn't seem
> to optimize it away in this case (a variant type used as an
> enumeration with only simple constructors).  I suppose that one
> solution would be to just use let-bindings to associate integers with
> names "by hand" instead of using the variant type.  I don't really
> like that approach too much, however.

Indeed, the compiler does not do it... yet. But it's already somewhere
on someone's TODO list ;-)

Fabrice

[-- Attachment #2: fabrice_le_fessant.vcf --]
[-- Type: text/x-vcard, Size: 380 bytes --]

begin:vcard
fn:Fabrice LE FESSANT
n:LE FESSANT;Fabrice
org:INRIA Saclay -- Ile-de-France;P2P & OCaml
adr;quoted-printable:;;Parc Orsay Universit=C3=A9 ;Orsay CEDEX;;91893;France
email;internet:fabrice.le_fessant@inria.fr
title;quoted-printable:Charg=C3=A9 de Recherche
tel;work:+33 1 74 85 42 14
tel;fax:+33 1 74 85 42 49 
url:http://fabrice.lefessant.net/
version:2.1
end:vcard


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

* Re: [Caml-list] Comparing variant types
  2011-04-28 19:16 [Caml-list] Comparing variant types Ethan Burns
  2011-04-28 21:07 ` Vincent Aravantinos
@ 2011-04-29  8:57 ` Dmitry Bely
       [not found] ` <164004794.892685.1304067487325.JavaMail.root@zmbs2.inria.fr>
  2 siblings, 0 replies; 16+ messages in thread
From: Dmitry Bely @ 2011-04-29  8:57 UTC (permalink / raw)
  To: caml-list

On Thu, Apr 28, 2011 at 11:16 PM, Ethan Burns <burns.ethan@gmail.com> wrote:
> Hi,
>
> I have a program that uses variant types as an enumeration.  While
> profiling, I noticed that compare_val was being called a bunch.  When
> I went to inspect why this was the case, it turns out that it was
> being called to compare equality of my variants.  I am a bit confused,
> however, because my understanding was that variants that are declared
> without an 'of' clause were just represented as integers and therefore
> a type containing only these simple elements should be directly
> comparable (no compare_val).
>
> While looking further into this, I found a little example where the
> compiler seems to produce a simple comparison in one case and not in
> another:
>
> type dir = Left | Right | Up | Down | No_op
>
> (* performs a simple comparison *)
> let f a = a <> Right
>
> (* calls out to C to do compare_val *)
> let g (a:dir) b = a <> b
>
> There is the -dlambda output:
>
> (seq
>  (let (f/69 (function a/70 (!= a/70 1a)))
>    (setfield_imm 0 (global Test!) f/69))
>  (let (g/71 (function a/72 b/73 (caml_notequal a/72 b/73)))
>    (setfield_imm 1 (global Test!) g/71))
>  0a)
>
> Since both functions know that the types of the elements being compare
> is 'dir', which contains only simple elements, why does the g function
> still use compare_val?  Does the compiler not perform this particular
> optimization?

I don't know why structured compare is not optimized, but physical one
(which does the same in your case) is optimized away as expected.

let g (a:dir) b = a != b

- Dmitry Bely


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

* Re: [Caml-list] Comparing variant types
       [not found] ` <164004794.892685.1304067487325.JavaMail.root@zmbs2.inria.fr>
@ 2011-04-29  9:33   ` luc.maranget
  2011-04-29 10:54     ` Andrew
                       ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: luc.maranget @ 2011-04-29  9:33 UTC (permalink / raw)
  To: Dmitry Bely; +Cc: caml-list

> > (* performs a simple comparison *)
> > let f a = a <> Right
> >
> > (* calls out to C to do compare_val *)
> > let g (a:dir) b = a <> b
> >
...
> 
> let g (a:dir) b = a != b
> 
> - Dmitry Bely
> 

As a general rule, don't do that! :)  (using <> or !=
for writing  'g').


For <>, you'll get hurt by data types with non-unique representation
(such as Set), as already pointed out.
It is ok to use structural equality when it is not the case, but
your programm is not as robust as you may want it to be.

For !=, it is much worse, as soon as you add a non-constant
constructor to your data type, your code is wrong
(cf. [1] != [1])

If you aim at robust  code. A recommended (tiresome) alternative
is to write your own equality function once for all, in
the following style.

type dir = Left | Right | Up | Down | No_op

let dir_equal d1 d2 = match d1,d2 with
| (Left, Left)
| (Right,Right)
| (Up, Up)
| (Down,Down)
| (No_op,No_op)
 -> true
| (Left,(Right|Up|Down|No_op))
| (Right,(Left|Up|Down|No_op))
| (Up,(Left|Right|Down|No_op))
| (Down,(Left|Right|Up|No_op))
| (No_op,(Down|Up|Right|Left))
-> false



let g a b = not (dir_equal a b)

Notice that 'let f a = a != Right' and 'let f a = a <> Right' are
less dangerous, but well...


--Luc

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

* Re: [Caml-list] Comparing variant types
  2011-04-29  9:33   ` luc.maranget
@ 2011-04-29 10:54     ` Andrew
  2011-04-29 11:17       ` Dmitry Bely
  2011-04-29 12:15       ` Jon Harrop
  2011-04-29 11:32     ` Dmitry Bely
  2011-04-30 13:43     ` craff73
  2 siblings, 2 replies; 16+ messages in thread
From: Andrew @ 2011-04-29 10:54 UTC (permalink / raw)
  To: caml-list

> type dir = Left | Right | Up | Down | No_op
>
> let dir_equal d1 d2 = match d1,d2 with
> | (Left, Left)
> | (Right,Right)
> | (Up, Up)
> | (Down,Down)
> | (No_op,No_op)
>   ->  true
> | (Left,(Right|Up|Down|No_op))
> | (Right,(Left|Up|Down|No_op))
> | (Up,(Left|Right|Down|No_op))
> | (Down,(Left|Right|Up|No_op))
> | (No_op,(Down|Up|Right|Left))
> ->  false


Why not write directly
	let dir_equal = fun d1 d2 ->
	  | Left Left
	  | Right Right
	  | Up Up
	  | Down Down
	  | No_op No_op ->  true
	  | _ -> false
?

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

* Re: [Caml-list] Comparing variant types
  2011-04-29 10:54     ` Andrew
@ 2011-04-29 11:17       ` Dmitry Bely
  2011-04-29 12:15       ` Jon Harrop
  1 sibling, 0 replies; 16+ messages in thread
From: Dmitry Bely @ 2011-04-29 11:17 UTC (permalink / raw)
  To: caml-list

On Fri, Apr 29, 2011 at 2:54 PM, Andrew <newsgroups.fr@gmail.com> wrote:
>> type dir = Left | Right | Up | Down | No_op
>>
>> let dir_equal d1 d2 = match d1,d2 with
>> | (Left, Left)
>> | (Right,Right)
>> | (Up, Up)
>> | (Down,Down)
>> | (No_op,No_op)
>>  ->  true
>> | (Left,(Right|Up|Down|No_op))
>> | (Right,(Left|Up|Down|No_op))
>> | (Up,(Left|Right|Down|No_op))
>> | (Down,(Left|Right|Up|No_op))
>> | (No_op,(Down|Up|Right|Left))
>> ->  false
>
>
> Why not write directly
>        let dir_equal = fun d1 d2 ->
>          | Left Left
>          | Right Right
>          | Up Up
>          | Down Down
>          | No_op No_op ->  true
>          | _ -> false

"Directly" means "syntactically incorrect"? :) As for _ clause - you'd
better to avoid it.

- Dmitry Bely


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

* Re: [Caml-list] Comparing variant types
  2011-04-29  9:33   ` luc.maranget
  2011-04-29 10:54     ` Andrew
@ 2011-04-29 11:32     ` Dmitry Bely
  2011-04-30 13:43     ` craff73
  2 siblings, 0 replies; 16+ messages in thread
From: Dmitry Bely @ 2011-04-29 11:32 UTC (permalink / raw)
  To: caml-list

On Fri, Apr 29, 2011 at 1:33 PM,  <luc.maranget@inria.fr> wrote:
>> > (* performs a simple comparison *)
>> > let f a = a <> Right
>> >
>> > (* calls out to C to do compare_val *)
>> > let g (a:dir) b = a <> b
>> >
> ...
>>
>> let g (a:dir) b = a != b
>>
>> - Dmitry Bely
>>
>
> As a general rule, don't do that! :)  (using <> or !=
> for writing  'g').
>
>
> For <>, you'll get hurt by data types with non-unique representation
> (such as Set), as already pointed out.
> It is ok to use structural equality when it is not the case, but
> your programm is not as robust as you may want it to be.
>
> For !=, it is much worse, as soon as you add a non-constant
> constructor to your data type, your code is wrong
> (cf. [1] != [1])
>
> If you aim at robust  code. A recommended (tiresome) alternative
> is to write your own equality function once for all, in
> the following style.
>
> type dir = Left | Right | Up | Down | No_op
>
> let dir_equal d1 d2 = match d1,d2 with
> | (Left, Left)
> | (Right,Right)
> | (Up, Up)
> | (Down,Down)
> | (No_op,No_op)
>  -> true
> | (Left,(Right|Up|Down|No_op))
> | (Right,(Left|Up|Down|No_op))
> | (Up,(Left|Right|Down|No_op))
> | (Down,(Left|Right|Up|No_op))
> | (No_op,(Down|Up|Right|Left))
> -> false

Yes, but Ethan's primary concern was efficiency. You dir_equal would
hardly fit (I'm afraid it's even more slow than <> because it's
translated into switch/case block). But generally speaking, of course
robustness is always the first priority.

- Dmitry Bely

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

* RE: [Caml-list] Comparing variant types
  2011-04-29 10:54     ` Andrew
  2011-04-29 11:17       ` Dmitry Bely
@ 2011-04-29 12:15       ` Jon Harrop
  2011-04-30 16:38         ` Andrew
  1 sibling, 1 reply; 16+ messages in thread
From: Jon Harrop @ 2011-04-29 12:15 UTC (permalink / raw)
  To: 'Andrew', caml-list

Andrew wrote:
> Why not write directly
> 	let dir_equal = fun d1 d2 ->
> 	  | Left Left
> 	  | Right Right
> 	  | Up Up
> 	  | Down Down
> 	  | No_op No_op ->  true
> 	  | _ -> false

You want to fill out your _ pattern with explicit type constructors
otherwise it is fragile wrt new constructors being added to the type.

Cheers,
Jon.



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

* Re: [Caml-list] Comparing variant types
  2011-04-29  9:33   ` luc.maranget
  2011-04-29 10:54     ` Andrew
  2011-04-29 11:32     ` Dmitry Bely
@ 2011-04-30 13:43     ` craff73
  2011-04-30 19:26       ` Andrew
  2011-04-30 20:19       ` Gabriel Scherer
  2 siblings, 2 replies; 16+ messages in thread
From: craff73 @ 2011-04-30 13:43 UTC (permalink / raw)
  To: luc.maranget, Dmitry Bely; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 303 bytes --]

Hello,

You want to avoid code size quadratic in the number of constructors. Which is possible:

let cmp x y = match x, y with
A, A -> true
| A, _ | _, A -> false
| B, B -> true
| B, _ | _, B -> false
...

Cheers
Christophe

-- 
Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.


[-- Attachment #2: Type: text/html, Size: 382 bytes --]

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

* Re: [Caml-list] Comparing variant types
  2011-04-29 12:15       ` Jon Harrop
@ 2011-04-30 16:38         ` Andrew
  0 siblings, 0 replies; 16+ messages in thread
From: Andrew @ 2011-04-30 16:38 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list

On Apr. 29, 2011, Jon Harrop <jon@ffconsultancy.com> wrote:
> Andrew wrote:
>> Why not write directly
>> 	let dir_equal = fun d1 d2 ->
>> 	| Left Left
>> 	  | Right Right
>> 	  | Up Up
>> 	  | Down Down
>> 	  | No_op No_op ->   true
>> 	  | _ ->  false
>
> You want to fill out your _ pattern with explicit type constructors
> otherwise it is fragile wrt new constructors being added to the type.

Oh, ok =)

> Cheers,
> Jon.

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

* Re: [Caml-list] Comparing variant types
  2011-04-30 13:43     ` craff73
@ 2011-04-30 19:26       ` Andrew
  2011-04-30 20:19       ` Gabriel Scherer
  1 sibling, 0 replies; 16+ messages in thread
From: Andrew @ 2011-04-30 19:26 UTC (permalink / raw)
  To: caml-list

> Hello,
>
> You want to avoid code size quadratic in the number of constructors. Which is possible:
>
> let cmp x y = match x, y with
> A, A -> true
> | A, _ | _, A -> false
> | B, B -> true
> | B, _ | _, B -> false
> ...

Yay! _ strikes back =)

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

* Re: [Caml-list] Comparing variant types
  2011-04-30 13:43     ` craff73
  2011-04-30 19:26       ` Andrew
@ 2011-04-30 20:19       ` Gabriel Scherer
  2011-04-30 20:57         ` Yaron Minsky
  1 sibling, 1 reply; 16+ messages in thread
From: Gabriel Scherer @ 2011-04-30 20:19 UTC (permalink / raw)
  To: craff73; +Cc: luc.maranget, Dmitry Bely, caml-list

[-- Attachment #1: Type: text/plain, Size: 1009 bytes --]

>
> You want to avoid code size quadratic in the number of constructors. Which
> is possible:
>


let cmp x y = match x, y with
> A, A -> true
> | A, _ | _, A -> false
> | B, B -> true
> | B, _ | _, B -> false


With one twist though: if done that way for (type foo = A | B), the last (_,
B) pattern is actually redundant. If you want to avoid getting a warning
here, you should comment it out or remove it:

  let cmp x y = match x, y with
  | A, A -> true
  | A, _ | _, A -> false
  | B, B -> true
  | B, _ (*| _, B*) -> false

That's the style I use.

On Sat, Apr 30, 2011 at 3:43 PM, craff73@gmail.com <craff73@gmail.com>wrote:

> Hello,
>
> You want to avoid code size quadratic in the number of constructors. Which
> is possible:
>
> let cmp x y = match x, y with
> A, A -> true
> | A, _ | _, A -> false
> | B, B -> true
> | B, _ | _, B -> false
> ...
>
> Cheers
> Christophe
>
> --
> Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.
>
>

[-- Attachment #2: Type: text/html, Size: 2272 bytes --]

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

* Re: [Caml-list] Comparing variant types
  2011-04-30 20:19       ` Gabriel Scherer
@ 2011-04-30 20:57         ` Yaron Minsky
  0 siblings, 0 replies; 16+ messages in thread
From: Yaron Minsky @ 2011-04-30 20:57 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: craff73, luc.maranget, Dmitry Bely, caml-list

[-- Attachment #1: Type: text/plain, Size: 1900 bytes --]

When I have to do this by hand, my favorite style is this:

type t = A of float | B of string

let compare x y =
   let tag_idx = function  A _ -> 0 | B _ -> 1 in
   match x, y with
   | A a1, A a2 -> Float.compare a1 a2
   | B b1, B b2 -> String.compare b1 b2
   | (B _ | A _), _ -> Int.compare (tag_idx x) (tag_idx y)

You will get the right kind of warnings when the type t changes, and it's
pleasantly explicit about the ordering implied by the tags.

That said, this is unpleasant boilerplate to have to write by hand.  My
expectation is that in the next release of Core, we will include a set of
macros for autogenerating equality, comparison and hash functions, as well
as type-hashes, all driven by the type definitions.

On Sat, Apr 30, 2011 at 4:19 PM, Gabriel Scherer
<gabriel.scherer@gmail.com>wrote:

> You want to avoid code size quadratic in the number of constructors. Which
>> is possible:
>>
>
>
> let cmp x y = match x, y with
>> A, A -> true
>> | A, _ | _, A -> false
>> | B, B -> true
>> | B, _ | _, B -> false
>
>
> With one twist though: if done that way for (type foo = A | B), the last
> (_, B) pattern is actually redundant. If you want to avoid getting a warning
> here, you should comment it out or remove it:
>
>   let cmp x y = match x, y with
>   | A, A -> true
>   | A, _ | _, A -> false
>   | B, B -> true
>   | B, _ (*| _, B*) -> false
>
> That's the style I use.
>
> On Sat, Apr 30, 2011 at 3:43 PM, craff73@gmail.com <craff73@gmail.com>wrote:
>
>> Hello,
>>
>> You want to avoid code size quadratic in the number of constructors. Which
>> is possible:
>>
>> let cmp x y = match x, y with
>> A, A -> true
>> | A, _ | _, A -> false
>> | B, B -> true
>> | B, _ | _, B -> false
>> ...
>>
>> Cheers
>> Christophe
>>
>> --
>> Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.
>>
>>
>

[-- Attachment #2: Type: text/html, Size: 3404 bytes --]

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

* Re: [Caml-list] Comparing variant types
       [not found] <fa.FGXk5PCsQgS8TidmFkgljpqbLZo@ifi.uio.no>
@ 2011-04-29 11:54 ` Ethan Burns
  0 siblings, 0 replies; 16+ messages in thread
From: Ethan Burns @ 2011-04-29 11:54 UTC (permalink / raw)
  To: fa.caml; +Cc: Dmitry Bely, caml-list

On Friday, April 29, 2011 5:34:16 AM UTC-4, luc.ma...@inria.fr wrote:
> As a general rule, don't do that! :)  (using <> or !=
> for writing  'g').
> 
> 
> For <>, you'll get hurt by data types with non-unique representation
> (such as Set), as already pointed out.
> It is ok to use structural equality when it is not the case, but
> your programm is not as robust as you may want it to be.

Well, in this case I am actually not really writing the function g and instead this comparison is embedded in another function somewhere.  My feeling was that using <> would be perfectly safe because it would translate to an integer comparison.  The structure of a type containing only simple constructors should be unique (I think they are all just mapped to ints).

> For !=, it is much worse, as soon as you add a non-constant
> constructor to your data type, your code is wrong
> (cf. [1] != [1])
> 
> If you aim at robust  code. A recommended (tiresome) alternative
> is to write your own equality function once for all, in
> the following style.
> 
> type dir = Left | Right | Up | Down | No_op
> 
> let dir_equal d1 d2 = match d1,d2 with
> | (Left, Left)
> | (Right,Right)
> | (Up, Up)
> | (Down,Down)
> | (No_op,No_op)
>  -> true
> | (Left,(Right|Up|Down|No_op))
> | (Right,(Left|Up|Down|No_op))
> | (Up,(Left|Right|Down|No_op))
> | (Down,(Left|Right|Up|No_op))
> | (No_op,(Down|Up|Right|Left))
> -> false

This is tiresome indeed!  Also, I am concerned that it is less efficient than just dropping down to compare_val (although I haven't tried it).  Since the type that I am using will only ever have a unique representation, I would love to avoid something like this.

I think that the solution that I will stick with for now is the one given by Dmitry (although I am typically not a fan of != in general).  Fabrice seemed to imply that optimizing <> in this case was 'in the works.'  I will be pretty happy to see that because I am sure that I have other code lying around somewhere that is assuming <> on a simple 'enum type' is just an integer comparison.


Best,
Ethan


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

end of thread, other threads:[~2011-04-30 20:57 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-28 19:16 [Caml-list] Comparing variant types Ethan Burns
2011-04-28 21:07 ` Vincent Aravantinos
2011-04-28 22:56   ` Ethan Burns
     [not found]   ` <354087020.772283.1304031467793.JavaMail.root@zmbs4.inria.fr>
2011-04-29  8:46     ` Fabrice Le Fessant
2011-04-29  8:57 ` Dmitry Bely
     [not found] ` <164004794.892685.1304067487325.JavaMail.root@zmbs2.inria.fr>
2011-04-29  9:33   ` luc.maranget
2011-04-29 10:54     ` Andrew
2011-04-29 11:17       ` Dmitry Bely
2011-04-29 12:15       ` Jon Harrop
2011-04-30 16:38         ` Andrew
2011-04-29 11:32     ` Dmitry Bely
2011-04-30 13:43     ` craff73
2011-04-30 19:26       ` Andrew
2011-04-30 20:19       ` Gabriel Scherer
2011-04-30 20:57         ` Yaron Minsky
     [not found] <fa.FGXk5PCsQgS8TidmFkgljpqbLZo@ifi.uio.no>
2011-04-29 11:54 ` Ethan Burns

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