caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* convenient features
@ 2000-06-28  9:44 David Chemouil
  2000-06-28 17:09 ` David Brown
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: David Chemouil @ 2000-06-28  9:44 UTC (permalink / raw)
  To: caml-list


Hi


participating to a former discussion about convenient features which
could be added to the Caml system, I'd like to inform you of a few 
critics, constructive critics of course ;-)

1. One thing that really bothers me is the obligation to put object
files in the good order, when linking them. As it is possible to
generate the dependency graph (ocamldot does it), wouldn't it be
possible for the linker to "flatten" it, in order for it to find alone
the good order? It seems to me that it works in C for example. So, one
would just have to put necessary object files on the command line, in
any order. 'Cause when you have 50 object files, or so, it's really
boring to find dependencies "by hand".

2. The second point is minor: it seems to me you only need to put the
'-thread' option when your program uses the 'threads.cm[x]a' library. So
it must be possible to remove the '-thread' option, and have the
compiler guess that the program is multithreaded when it sees
'threads.cm[x]a' on the command line.

3. The last point seems important to me. When you use bytecode threads,
marshalling with the Marshal module doesn't work well. Isn't it possible
that the compiler automatically replaces it by a working one, like it
does with Pervasives? 


dc

-- 
David Chemouil [mailto:chemouil@enseeiht.fr] [mobile: 06 84 16 26 65]

Laboratoire d'informatique et de mathématiques appliquées (IRIT-INPT)

"Je vous ai fait trop faibles pour sortir du gouffre, parce que 
 je vous ai fait assez forts pour n'y point tomber" -- Rousseau



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

* Re: convenient features
  2000-06-28  9:44 convenient features David Chemouil
@ 2000-06-28 17:09 ` David Brown
  2000-06-28 17:29 ` Markus Mottl
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: David Brown @ 2000-06-28 17:09 UTC (permalink / raw)
  To: David Chemouil; +Cc: caml-list

On Wed, Jun 28, 2000 at 11:44:54AM +0200, David Chemouil wrote:
> 1. One thing that really bothers me is the obligation to put object
> files in the good order, when linking them. As it is possible to
> generate the dependency graph (ocamldot does it), wouldn't it be
> possible for the linker to "flatten" it, in order for it to find alone
> the good order? It seems to me that it works in C for example. So, one
> would just have to put necessary object files on the command line, in
> any order. 'Cause when you have 50 object files, or so, it's really
> boring to find dependencies "by hand".
> 
> 2. The second point is minor: it seems to me you only need to put the
> '-thread' option when your program uses the 'threads.cm[x]a' library. So
> it must be possible to remove the '-thread' option, and have the
> compiler guess that the program is multithreaded when it sees
> 'threads.cm[x]a' on the command line.

A while back, I wrote up a small utility that I called ocamlmake.  It takes
as an argument a single module name.  It runs ocamldep (actually I put the
ocamldep code in it) to determine module dependencies and ordering.  It
would scan for use of threads and unix (and other) libraries and compile
appropriately.

I need to rewrite it to use the new ocamllex, and with the new copyright, I
can actually distribute what I produce.

Is there interest in such a beast?

Dave Brown



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

* Re: convenient features
  2000-06-28  9:44 convenient features David Chemouil
  2000-06-28 17:09 ` David Brown
@ 2000-06-28 17:29 ` Markus Mottl
  2000-06-29 16:57   ` Pierre Weis
  2000-06-29  8:55 ` David Mentré
  2000-06-29  9:19 ` Daniel de Rauglaudre
  3 siblings, 1 reply; 9+ messages in thread
From: Markus Mottl @ 2000-06-28 17:29 UTC (permalink / raw)
  To: David Chemouil; +Cc: caml-list

On Wed, 28 Jun 2000, David Chemouil wrote:
> 1. One thing that really bothers me is the obligation to put object
> files in the good order, when linking them.

To my knowledge the reason for this is that you might otherwise have
difficulties with linking, because some library may contain a module
with the same name. By requiring correct order of files during linking,
it is possible to "override" the names provided in libraries or earlier
on the command line. E.g., if you want to use a different implementation
for sets, just link against some other set.cmo: it overrides whatever
was used before.

> As it is possible to
> generate the dependency graph (ocamldot does it), wouldn't it be
> possible for the linker to "flatten" it, in order for it to find alone
> the good order?

Maybe a tool that prints out a correct order for a set of files would
be helpful. This should be fairly easy to do - possibly just grab the
code from ocamldot.

Best regards,
Markus Mottl

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl



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

* Re: convenient features
  2000-06-28  9:44 convenient features David Chemouil
  2000-06-28 17:09 ` David Brown
  2000-06-28 17:29 ` Markus Mottl
@ 2000-06-29  8:55 ` David Mentré
  2000-06-29  9:19 ` Daniel de Rauglaudre
  3 siblings, 0 replies; 9+ messages in thread
From: David Mentré @ 2000-06-29  8:55 UTC (permalink / raw)
  To: David Chemouil; +Cc: caml-list

David Chemouil <David.Chemouil@enseeiht.fr> writes:

> 1. One thing that really bothers me is the obligation to put object
> files in the good order, when linking them.

ocamldep is your friend (included in the standard distribution). Have a
look at the following makefile to see how to use it:

http://caml.inria.fr/FAQ/Makefile_ocaml-eng.html


Otherwise, there is also OCaml Make from Markus (i've never used it):

  http://miss.wu-wien.ac.at/~mottl/ocaml_sources/intro.html


> 2. [...] So it must be possible to remove the '-thread' option, and
> have the compiler guess that the program is multithreaded when it sees
> 'threads.cm[x]a' on the command line.

I think this option is due to separate compilation. You may compile a
file in reentrant mode (aka multi-threaded) without doing the link phase
(with the threads.cm[x]a library).


Best regards,
david
-- 
 David.Mentre@irisa.fr -- http://www.irisa.fr/prive/dmentre/
 Opinions expressed here are only mine.



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

* Re: convenient features
  2000-06-28  9:44 convenient features David Chemouil
                   ` (2 preceding siblings ...)
  2000-06-29  8:55 ` David Mentré
@ 2000-06-29  9:19 ` Daniel de Rauglaudre
  2000-06-30  0:42   ` Max Skaller
  3 siblings, 1 reply; 9+ messages in thread
From: Daniel de Rauglaudre @ 2000-06-29  9:19 UTC (permalink / raw)
  To: caml-list

Hello,

On Wed, Jun 28, 2000 at 11:44:54AM +0200, David Chemouil wrote:

> 1. One thing that really bothers me is the obligation to put object
> files in the good order, when linking them. As it is possible to
> generate the dependency graph (ocamldot does it), wouldn't it be
> possible for the linker to "flatten" it, in order for it to find alone
> the good order?

I personnally consider that it would be a good idea, but there is a little
problem. Let's consider:
   a.ml depending on c.ml (a.ml contains e.g. open C)
   b.ml independant
   c.ml independant

Let's suppose that you write:
    ocamlc a.cmo b.cmo c.cmo

Do Ocaml has to do:
    ocamlc c.cmo a.cmo b.cmo
    ocamlc b.cmo c.cmo a.cmo

The first solution respects the initial relative order "a.cmo b.cmo" but
not "b.cmo c.cmo". It is the contrary in the second solution.

If Ocaml chooses for you, it can be a problem if you want to make side
effects in some order while executing these modules.

Well, it could be an option of Ocaml...

I have been inspired by this question by my genealogy software GeneWeb
when I have to sort children by birth dates when not all of them have some.

-- 
Daniel de RAUGLAUDRE
daniel.de_rauglaudre@inria.fr
http://cristal.inria.fr/~ddr/



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

* Re: convenient features
  2000-06-28 17:29 ` Markus Mottl
@ 2000-06-29 16:57   ` Pierre Weis
  2000-06-30  9:22     ` Christophe Raffalli
  0 siblings, 1 reply; 9+ messages in thread
From: Pierre Weis @ 2000-06-29 16:57 UTC (permalink / raw)
  To: Markus Mottl; +Cc: caml-list

> On Wed, 28 Jun 2000, David Chemouil wrote:
> > 1. One thing that really bothers me is the obligation to put object
> > files in the good order, when linking them.
> 
> To my knowledge the reason for this is that you might otherwise have
> difficulties with linking, because some library may contain a module
> with the same name. By requiring correct order of files during linking,
> it is possible to "override" the names provided in libraries or earlier
> on the command line. E.g., if you want to use a different implementation
> for sets, just link against some other set.cmo: it overrides whatever
> was used before.

You're right, but also don't forget that toplevel expressions in
modules are executed in the order of presentation (and recursively,
that is in each module, for all the modules that are linked together).

This way, if init.ml contains the expression initialize ();;
and main.ml contains exit 0;; as its last phrase, then linking init.cmx
before main.cmx ensures that initialization is performed before
exiting the program.

Best regards,

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/




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

* Re: convenient features
  2000-06-29  9:19 ` Daniel de Rauglaudre
@ 2000-06-30  0:42   ` Max Skaller
  0 siblings, 0 replies; 9+ messages in thread
From: Max Skaller @ 2000-06-30  0:42 UTC (permalink / raw)
  To: Daniel de Rauglaudre; +Cc: caml-list

Daniel de Rauglaudre wrote:

> If Ocaml chooses for you, it can be a problem if you want to make side
> effects in some order while executing these modules.

Then you could either:

	1) add a dummy dependency in, to force the ordering

This is a hack, but so is using side effects to initialise modules :-)

	2) think about a language feature to replace the dummy
dependency. In Python, you have to explicitly import a module
before you can use it. In C, you have to explicitly #include a file
before you can use the resources it represents the interface for.
In ocaml, the lack of such a requirement could be viewed as a design
flaw:
it is hard to tell what a module depends on by inspection ( you have too
look
at every line of code carefully to find which names are module names).

An 'import' or 'use' statement might also allow a local name for the
module.
(Unlike 'open', a such a statement doesn't make the symbols defined in
the
module available unqualified).

A possible extension: to instantiate a functor (i.e. use an instance
of a functor module).


-- 
John (Max) Skaller at OTT [Open Telecommications Ltd]
mailto:maxs@in.ot.com.au      -- at work
mailto:skaller@maxtal.com.au  -- at home



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

* Re: convenient features
  2000-06-29 16:57   ` Pierre Weis
@ 2000-06-30  9:22     ` Christophe Raffalli
  2000-06-30 18:10       ` Jean-Christophe Filliatre
  0 siblings, 1 reply; 9+ messages in thread
From: Christophe Raffalli @ 2000-06-30  9:22 UTC (permalink / raw)
  Cc: caml-list


I have a problem to define a type ! 
Whe I want is the following (which is incorrect !)


(* index in a sequence *)
type index = { 
  index_key : int; 
  mutable index_val : index_val
} 
and index_val =
    Noval of index list 
  | Hasval of index * IndexSet.t

and module Index =
struct
  type t = index
  let compare i j = i.index_key - j.index_key
end

and module IndexSet = Set.Make(Index)

Does someone see a solution ? ( I have a soliution using Obj.t ... But
it is not reasonnable)
 
-- 
Christophe Raffalli
Université de Savoie
Batiment Le Chablais, bureau 21
73376 Le Bourget-du-Lac Cedex

tél: (33) 4 79 75 81 03
fax: (33) 4 79 75 87 42
mail: Christophe.Raffalli@univ-savoie.fr
www: http://www.lama.univ-savoie.fr/~RAFFALLI



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

* Re: convenient features
  2000-06-30  9:22     ` Christophe Raffalli
@ 2000-06-30 18:10       ` Jean-Christophe Filliatre
  0 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe Filliatre @ 2000-06-30 18:10 UTC (permalink / raw)
  To: Christophe Raffalli; +Cc: caml-list


In his message of Fri June 30, 2000, Christophe Raffalli writes: 
> 
> I have a problem to define a type ! 
> Whe I want is the following (which is incorrect !)
>
> type index = { 
>   index_key : int; 
>   mutable index_val : index_val
> } 
> and index_val =
>     Noval of index list 
>   | Hasval of index * IndexSet.t
> 
> and module Index =
> struct
>   type t = index
>   let compare i j = i.index_key - j.index_key
> end
> 
> and module IndexSet = Set.Make(Index)

There is  at least one solution,  if you consider a  version of module
Set with a type parameter, which I include at the end of this mail. If
that module is called Pset, then you can define your types like this:

======================================================================
type 'a indexed = {
  index : int;
  mutable value : 'a }

module IndexSet = Pset.Make(
  struct
    type 'a t = 'a indexed
    let compare x y = x.index - y.index
  end)

type index = index_val indexed

and index_val =
    Noval of index list 
  | Hasval of index * index_val IndexSet.t
======================================================================

Remark: to define module Pset, you  don't need to change the code, but
only the  types to add a  type parameter 'a in  both functor arguments
and results.

-- 
Jean-Christophe Filliatre    
  Computer Science Laboratory   Phone (650) 859-5173
  SRI International             FAX   (650) 859-2844
  333 Ravenswood Ave.           email filliatr@csl.sri.com
  Menlo Park, CA 94025, USA     web   http://www.csl.sri.com/~filliatr

= pset.mli ===========================================================
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
(*                                                                     *)
(*  Copyright 1996 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the GNU Library General Public License.         *)
(*                                                                     *)
(***********************************************************************)

(* $Id: set.mli,v 1.19 2000/04/13 12:16:26 xleroy Exp $ *)

(* Module [Set]: sets over ordered types *)

(* This module implements the set data structure, given a total ordering
   function over the set elements. All operations over sets
   are purely applicative (no side-effects).
   The implementation uses balanced binary trees, and is therefore
   reasonably efficient: insertion and membership take time
   logarithmic in the size of the set, for instance. *)

module type POrderedType =
  sig
    type 'a t
    val compare: 'a t -> 'a t -> int
  end
          (* The input signature of the functor [Set.Make].
             [t] is the type of the set elements.
             [compare] is a total ordering function over the set elements.
             This is a two-argument function [f] such that
             [f e1 e2] is zero if the elements [e1] and [e2] are equal,
             [f e1 e2] is strictly negative if [e1] is smaller than [e2],
             and [f e1 e2] is strictly positive if [e1] is greater than [e2].
             Example: a suitable ordering function is
             the generic structural comparison function [compare]. *)

module type S =
  sig
    type 'a elt
          (* The type of the set elements. *)
    type 'a t
          (* The type of sets. *)
    val empty: 'a t
          (* The empty set. *)
    val is_empty: 'a t -> bool
        (* Test whether a set is empty or not. *)
    val mem: 'a elt -> 'a t -> bool
        (* [mem x s] tests whether [x] belongs to the set [s]. *)
    val add: 'a elt -> 'a t -> 'a t
        (* [add x s] returns a set containing all elements of [s],
           plus [x]. If [x] was already in [s], [s] is returned unchanged. *)
    val singleton: 'a elt -> 'a t
        (* [singleton x] returns the one-element set containing only [x]. *)
    val remove: 'a elt -> 'a t -> 'a t
        (* [remove x s] returns a set containing all elements of [s],
           except [x]. If [x] was not in [s], [s] is returned unchanged. *)
    val union: 'a t -> 'a t -> 'a t
    val inter: 'a t -> 'a t -> 'a t
    val diff: 'a t -> 'a t -> 'a t
        (* Union, intersection and set difference. *)
    val compare: 'a t -> 'a t -> int
        (* Total ordering between sets. Can be used as the ordering function
           for doing sets of sets. *)
    val equal: 'a t -> 'a t -> bool
        (* [equal s1 s2] tests whether the sets [s1] and [s2] are
           equal, that is, contain equal elements. *)
    val subset: 'a t -> 'a t -> bool
        (* [subset s1 s2] tests whether the set [s1] is a subset of
           the set [s2]. *)
    val iter: f:('a elt -> unit) -> 'a t -> unit
        (* [iter f s] applies [f] in turn to all elements of [s].
           The order in which the elements of [s] are presented to [f]
           is unspecified. *)
    val fold: f:('a elt -> 'b -> 'b) -> 'a t -> init:'b -> 'b
        (* [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)],
           where [x1 ... xN] are the elements of [s].
           The order in which elements of [s] are presented to [f] is
           unspecified. *)
    val for_all: f:('a elt -> bool) -> 'a t -> bool
        (* [for_all p s] checks if all elements of the set
           satisfy the predicate [p]. *)
    val exists: f:('a elt -> bool) -> 'a t -> bool
        (* [exists p s] checks if at least one element of
           the set satisfies the predicate [p]. *)
    val filter: f:('a elt -> bool) -> 'a t -> 'a t
        (* [filter p s] returns the set of all elements in [s]
           that satisfy predicate [p]. *)
    val partition: f:('a elt -> bool) -> 'a t -> 'a t * 'a t
        (* [partition p s] returns a pair of sets [(s1, s2)], where
           [s1] is the set of all the elements of [s] that satisfy the
           predicate [p], and [s2] is the set of all the elements of
           [s] that do not satisfy [p]. *)
    val cardinal: 'a t -> int
        (* Return the number of elements of a set. *)
    val elements: 'a t -> 'a elt list
        (* Return the list of all elements of the given set.
           The returned list is sorted in increasing order with respect
           to the ordering [Ord.compare], where [Ord] is the argument
           given to [Set.Make]. *)
    val min_elt: 'a t -> 'a elt
        (* Return the smallest element of the given set
           (with respect to the [Ord.compare] ordering), or raise
           [Not_found] if the set is empty. *)
    val max_elt: 'a t -> 'a elt
        (* Same as [min_elt], but returns the largest element of the
           given set. *)
    val choose: 'a t -> 'a elt
        (* Return one element of the given set, or raise [Not_found] if
           the set is empty. Which element is chosen is unspecified,
           but equal elements will be chosen for equal sets. *)
  end

module Make(Ord: POrderedType): (S with type 'a elt = 'a Ord.t)
        (* Functor building an implementation of the set structure
           given a totally ordered type. *)

======================================================================

== pset.ml ===========================================================
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
(*                                                                     *)
(*  Copyright 1996 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the GNU Library General Public License.         *)
(*                                                                     *)
(***********************************************************************)

(* $Id: set.ml,v 1.13 2000/04/13 12:16:26 xleroy Exp $ *)

(* Sets over ordered types *)

module type POrderedType =
  sig
    type 'a t
    val compare: 'a t -> 'a t -> int
  end

module type S =
  sig
    type 'a elt
    type 'a t
    val empty: 'a t
    val is_empty: 'a t -> bool
    val mem: 'a elt -> 'a t -> bool
    val add: 'a elt -> 'a t -> 'a t
    val singleton: 'a elt -> 'a t
    val remove: 'a elt -> 'a t -> 'a t
    val union: 'a t -> 'a t -> 'a t
    val inter: 'a t -> 'a t -> 'a t
    val diff: 'a t -> 'a t -> 'a t
    val compare: 'a t -> 'a t -> int
    val equal: 'a t -> 'a t -> bool
    val subset: 'a t -> 'a t -> bool
    val iter: ('a elt -> unit) -> 'a t -> unit
    val fold: ('a elt -> 'b -> 'b) -> 'a t -> 'b -> 'b
    val for_all: ('a elt -> bool) -> 'a t -> bool
    val exists: ('a elt -> bool) -> 'a t -> bool
    val filter: ('a elt -> bool) -> 'a t -> 'a t
    val partition: ('a elt -> bool) -> 'a t -> 'a t * 'a t
    val cardinal: 'a t -> int
    val elements: 'a t -> 'a elt list
    val min_elt: 'a t -> 'a elt
    val max_elt: 'a t -> 'a elt
    val choose: 'a t -> 'a elt
  end

module Make(Ord: POrderedType) =
  struct
    type 'a elt = 'a Ord.t
    type 'a t = Empty | Node of 'a t * 'a elt * 'a t * int

    (* Sets are represented by balanced binary trees (the heights of the
       children differ by at most 2 *)

    let height = function
        Empty -> 0
      | Node(_, _, _, h) -> h

    (* Creates a new node with left son l, value x and right son r.
       l and r must be balanced and | height l - height r | <= 2.
       Inline expansion of height for better speed. *)

    let create l x r =
      let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
      let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
      Node(l, x, r, (if hl >= hr then hl + 1 else hr + 1))

    (* Same as create, but performs one step of rebalancing if necessary.
       Assumes l and r balanced.
       Inline expansion of create for better speed in the most frequent case
       where no rebalancing is required. *)

    let bal l x r =
      let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
      let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
      if hl > hr + 2 then begin
        match l with
          Empty -> invalid_arg "Set.bal"
        | Node(ll, lv, lr, _) ->
            if height ll >= height lr then
              create ll lv (create lr x r)
            else begin
              match lr with
                Empty -> invalid_arg "Set.bal"
              | Node(lrl, lrv, lrr, _)->
                  create (create ll lv lrl) lrv (create lrr x r)
            end
      end else if hr > hl + 2 then begin
        match r with
          Empty -> invalid_arg "Set.bal"
        | Node(rl, rv, rr, _) ->
            if height rr >= height rl then
              create (create l x rl) rv rr
            else begin
              match rl with
                Empty -> invalid_arg "Set.bal"
              | Node(rll, rlv, rlr, _) ->
                  create (create l x rll) rlv (create rlr rv rr)
            end
      end else
        Node(l, x, r, (if hl >= hr then hl + 1 else hr + 1))

    (* Same as bal, but repeat rebalancing until the final result
       is balanced. *)

    let rec join l x r =
      match bal l x r with
        Empty -> invalid_arg "Set.join"
      | Node(l', x', r', _) as t' ->
          let d = height l' - height r' in
          if d < -2 or d > 2 then join l' x' r' else t'

    (* Merge two trees l and r into one.
       All elements of l must precede the elements of r.
       Assumes | height l - height r | <= 2. *)

    let rec merge t1 t2 =
      match (t1, t2) with
        (Empty, t) -> t
      | (t, Empty) -> t
      | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
          bal l1 v1 (bal (merge r1 l2) v2 r2)

    (* Same as merge, but does not assume anything about l and r. *)

    let rec concat t1 t2 =
      match (t1, t2) with
        (Empty, t) -> t
      | (t, Empty) -> t
      | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
          join l1 v1 (join (concat r1 l2) v2 r2)

    (* Splitting *)

    let rec split x = function
        Empty ->
          (Empty, None, Empty)
      | Node(l, v, r, _) ->
          let c = Ord.compare x v in
          if c = 0 then (l, Some v, r)
          else if c < 0 then
            let (ll, vl, rl) = split x l in (ll, vl, join rl v r)
          else
            let (lr, vr, rr) = split x r in (join l v lr, vr, rr)

    (* Implementation of the set operations *)

    let empty = Empty

    let is_empty = function Empty -> true | _ -> false

    let rec mem x = function
        Empty -> false
      | Node(l, v, r, _) ->
          let c = Ord.compare x v in
          c = 0 || mem x (if c < 0 then l else r)

    let rec add x = function
        Empty -> Node(Empty, x, Empty, 1)
      | Node(l, v, r, _) as t ->
          let c = Ord.compare x v in
          if c = 0 then t else
          if c < 0 then bal (add x l) v r else bal l v (add x r)

    let singleton x = Node(Empty, x, Empty, 1)

    let rec remove x = function
        Empty -> Empty
      | Node(l, v, r, _) ->
          let c = Ord.compare x v in
          if c = 0 then merge l r else
          if c < 0 then bal (remove x l) v r else bal l v (remove x r)

    let rec union s1 s2 =
      match (s1, s2) with
        (Empty, t2) -> t2
      | (t1, Empty) -> t1
      | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
          if h1 >= h2 then
            if h2 = 1 then add v2 s1 else begin
              let (l2, _, r2) = split v1 s2 in
              join (union l1 l2) v1 (union r1 r2)
            end
          else
            if h1 = 1 then add v1 s2 else begin
              let (l1, _, r1) = split v2 s1 in
              join (union l1 l2) v2 (union r1 r2)
            end

    let rec inter s1 s2 =
      match (s1, s2) with
        (Empty, t2) -> Empty
      | (t1, Empty) -> Empty
      | (Node(l1, v1, r1, _), t2) ->
          match split v1 t2 with
            (l2, None, r2) ->
              concat (inter l1 l2) (inter r1 r2)
          | (l2, Some _, r2) ->
              join (inter l1 l2) v1 (inter r1 r2)

    let rec diff s1 s2 =
      match (s1, s2) with
        (Empty, t2) -> Empty
      | (t1, Empty) -> t1
      | (Node(l1, v1, r1, _), t2) ->
          match split v1 t2 with
            (l2, None, r2) ->
              join (diff l1 l2) v1 (diff r1 r2)
          | (l2, Some _, r2) ->
              concat (diff l1 l2) (diff r1 r2)

    let rec compare_aux l1 l2 =
        match (l1, l2) with
        ([], []) -> 0
      | ([], _)  -> -1
      | (_, []) -> 1
      | (Empty :: t1, Empty :: t2) ->
          compare_aux t1 t2
      | (Node(Empty, v1, r1, _) :: t1, Node(Empty, v2, r2, _) :: t2) ->
          let c = Ord.compare v1 v2 in
          if c <> 0 then c else compare_aux (r1::t1) (r2::t2)
      | (Node(l1, v1, r1, _) :: t1, t2) ->
          compare_aux (l1 :: Node(Empty, v1, r1, 0) :: t1) t2
      | (t1, Node(l2, v2, r2, _) :: t2) ->
          compare_aux t1 (l2 :: Node(Empty, v2, r2, 0) :: t2)

    let compare s1 s2 =
      compare_aux [s1] [s2]

    let equal s1 s2 =
      compare s1 s2 = 0

    let rec subset s1 s2 =
      match (s1, s2) with
        Empty, _ ->
          true
      | _, Empty ->
          false
      | Node (l1, v1, r1, _), (Node (l2, v2, r2, _) as t2) ->
          let c = Ord.compare v1 v2 in
          if c = 0 then
            subset l1 l2 && subset r1 r2
          else if c < 0 then
            subset (Node (l1, v1, Empty, 0)) l2 && subset r1 t2
          else
            subset (Node (Empty, v1, r1, 0)) r2 && subset l1 t2

    let rec iter f = function
        Empty -> ()
      | Node(l, v, r, _) -> iter f l; f v; iter f r

    let rec fold f s accu =
      match s with
        Empty -> accu
      | Node(l, v, r, _) -> fold f l (f v (fold f r accu))

    let rec for_all p = function
        Empty -> true
      | Node(l, v, r, _) -> p v && for_all p l && for_all p r

    let rec exists p = function
        Empty -> false
      | Node(l, v, r, _) -> p v || exists p l || exists p r

    let filter p s =
      let rec filt accu = function
        | Empty -> accu
        | Node(l, v, r, _) ->
            filt (filt (if p v then add v accu else accu) l) r in
      filt Empty s

    let partition p s =
      let rec part (t, f as accu) = function
        | Empty -> accu
        | Node(l, v, r, _) ->
            part (part (if p v then (add v t, f) else (t, add v f)) l) r in
      part (Empty, Empty) s

    let rec cardinal = function
        Empty -> 0
      | Node(l, v, r, _) -> cardinal l + 1 + cardinal r

    let rec elements_aux accu = function
        Empty -> accu
      | Node(l, v, r, _) -> elements_aux (v :: elements_aux accu r) l

    let elements s =
      elements_aux [] s

    let rec min_elt = function
        Empty -> raise Not_found
      | Node(Empty, v, r, _) -> v
      | Node(l, v, r, _) -> min_elt l

    let rec max_elt = function
        Empty -> raise Not_found
      | Node(l, v, Empty, _) -> v
      | Node(l, v, r, _) -> max_elt r

    let choose = min_elt

  end
======================================================================
  



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

end of thread, other threads:[~2000-07-01  8:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-06-28  9:44 convenient features David Chemouil
2000-06-28 17:09 ` David Brown
2000-06-28 17:29 ` Markus Mottl
2000-06-29 16:57   ` Pierre Weis
2000-06-30  9:22     ` Christophe Raffalli
2000-06-30 18:10       ` Jean-Christophe Filliatre
2000-06-29  8:55 ` David Mentré
2000-06-29  9:19 ` Daniel de Rauglaudre
2000-06-30  0:42   ` Max Skaller

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