Version française
Home     About     Download     Resources     Contact us    
Browse thread
Variants & structural ordering
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Berke Durak <berke.durak@e...>
Subject: Re: [Caml-list] Variants & structural ordering
Damien Guichard a écrit :

> Hi everybody,

Hello

> Typically, when you declare:
>  
> type card =
>   | Card of int
>   | Jack
>   | Queen
>   | King
>   | Ace
>   ;;
>  
> The relation you wish is:
>  
> Card(2) < ...< Card(10) < Jack < Queen < King < Ace
>  
> And that's what you get when using F#.

Thanks for this bit of knowledge about F#.

> However when using OCaml here is what you get:
>  
> Jack < Queen < King < Ace < Card(2) < ...< Card(10)
>  
> And the work-around is:
>  
> type card =
>   | Card of int
>   | Jack of unit
>   | Queen of unit
>   | King of unit
>   | Ace of unit
>   ;;
>  
> Is this a bug or a feature ?

Neither:  You are not supposed to assume anything on the way compare orders non-primitive types.

Constructors without arguments are represented as integers, which, as primitive types,
come before blocks, which are used to represent the values of constructors with arguments.

The "compare" functions give an ad-hoc order, the only guarantee being that it
will be a good ordering.  I think you can safely assume that it won't change accross Ocaml
releases (unless you start using a new VM.)

In practice, people often assume that the components of tuples and records are compared
in the same order as their components are given.  Relying on the order of enumerated types
is more risky: you provide a good example of this.

> Will it change in a foreseable future ?

I really don't think so and even if it did, there is no reason why it would change in the
way that would be useful to you in that particular case, and even then, it would be risky
to depend on that behaviour, and, besides, what's the point?  Simply use something like:

let max_card = 10

let int_of_card = function
| Card n -> assert(n < max_card); n
| Jack -> max_card
| Queen -> max_card + 1
| King -> max_card + 2

let compare c1 c2 = compare (int_of_card c1) (int_of_card c2)
-- 
Berke DURAK