Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* Type-checking bug (or feature?) in O'Caml 1.06
@ 1997-11-18 18:57 Paul Stodghill
  1997-11-18 19:05 ` Paul Stodghill
  1997-11-19  9:24 ` Pierre Weis
  0 siblings, 2 replies; 4+ messages in thread
From: Paul Stodghill @ 1997-11-18 18:57 UTC (permalink / raw)
  To: caml-list

[ Pardon, mais non français. ]

Something changed in the way that type checking is done between 1.05 and
1.06. Bug or feature?

% ~pidgin/sww/sparc-solaris/bin/ocamlc -v
The Objective Caml compiler, version 1.05
Standard library directory: /usr/u/pidgin/sww/sun4-solaris/lib/ocaml
% ~pidgin/sww/sparc-solaris/bin/ocamlc -c caml_map.mli
% ~pidgin/sww/sparc-solaris/bin/ocamlc -c caml_map.ml

% ~/usr/sparc-solaris/bin/ocamlc -v
The Objective Caml compiler, version 1.06
Standard library directory: /home/stodghil/usr/sparc-solaris/lib/ocaml
% ~/usr/sparc-solaris/bin/ocamlc -c caml_map.mli
% ~/usr/sparc-solaris/bin/ocamlc -c caml_map.ml
The implementation caml_map.ml does not match the interface caml_map.cmi:
Values do not match:
  val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
is not included in
  val iter : ('a -> 'b -> 'c) -> ('a, 'b) t -> unit

Below are the relevant parts of the code that is causing the problem.
This code is taken directly from the compatibility library generated by
caml2cslV2.0.

>From caml_map.mli:
---------------------------------------------------------------------------
val iter: ('a -> 'b -> 'c) -> ('a, 'b) t -> unit
---------------------------------------------------------------------------

>From caml_map.ml:
---------------------------------------------------------------------------
let iter f m =
  let rec iter = function
    Empty -> ()
  | Node(l, b, r, _) ->
      iter l;
      f b.key b.data;
      List.iter (f b.key) b.prev;
      iter r
  in iter m.tree;;
---------------------------------------------------------------------------

-- 
Paul Stodghill <stodghil@cs.cornell.edu>
http://www.cs.cornell.edu/home/stodghil/home.html





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

* Re: Type-checking bug (or feature?) in O'Caml 1.06
  1997-11-18 18:57 Type-checking bug (or feature?) in O'Caml 1.06 Paul Stodghill
@ 1997-11-18 19:05 ` Paul Stodghill
  1997-11-19  9:39   ` Pierre Weis
  1997-11-19  9:24 ` Pierre Weis
  1 sibling, 1 reply; 4+ messages in thread
From: Paul Stodghill @ 1997-11-18 19:05 UTC (permalink / raw)
  To: caml-list

The new behavior is even more bizarre than I had first thought.

---------------------------------------------------------------------------
% cat foo.mli
type ('a, 'b) t;;
val iter: ('a -> 'b -> 'unit) -> ('a, 'b) t -> unit

% ocamlc -v -i -c foo.mli
The Objective Caml compiler, version 1.06
Standard library directory: /home/stodghil/usr/sparc-solaris/lib/ocaml
type ('a, 'b) t
val iter : ('a -> 'b -> 'c) -> ('a, 'b) t -> unit
% 
---------------------------------------------------------------------------

Why is the generated type different than the declared type?

-- 
Paul Stodghill <stodghil@cs.cornell.edu>
http://www.cs.cornell.edu/home/stodghil/home.html





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

* Re: Type-checking bug (or feature?) in O'Caml 1.06
  1997-11-18 18:57 Type-checking bug (or feature?) in O'Caml 1.06 Paul Stodghill
  1997-11-18 19:05 ` Paul Stodghill
@ 1997-11-19  9:24 ` Pierre Weis
  1 sibling, 0 replies; 4+ messages in thread
From: Pierre Weis @ 1997-11-19  9:24 UTC (permalink / raw)
  To: Paul Stodghill; +Cc: caml-list

> [ Pardon, mais non français. ]
> 
> Something changed in the way that type checking is done between 1.05 and
> 1.06. Bug or feature?

What's up, doc ?
----------------

Yes something has changed: the type of iter functionals in the
library. The function to be iterated has now to have unit as target
type, instead of having a polymorphic 'c target. For instance,
List.iter is now declared as

List.iter : ('a -> unit) -> 'a list -> unit

You may ask why this change has beeen done ? The answer is simply to catch
more programming errors than before.

In particular, this is useful to avoid iteration of a partially
evaluated function, that (silently) does nothing at all. As an
example, consider:

let format_ints i j = printf "%d : %d, " i j;;

With the old prototype for List.iter, you get:

        Objective Caml version 1.05

# [...]
# List.iter format_ints [1;2;3];;
- : unit = ()

This bug may be very tedious to find in the middle of a huge
program. Now, compare with the new version of O'Caml:

        Objective Caml version 1.06

# [...]
# List.iter format_ints [1;2;3];;
This expression has type int -> int -> unit but is here used with type
  int -> unit

The ``effect free'' wrong iteration bug has been statically trapped.

This behaviour is more consistant with the safe programming standards
of Caml :)

What have I to modify in my existing programs ?
-----------------------------------------------
Several cases:
 (0) : the new prototype for iter find a bug in your program. Thanks
       the new behaviour of O'Caml and correct your bug.
 (1) : you already have defined some iter functional in your
       modules. To be consistent, update their profiles to the new one.
 (2) : you were iterating functions with the wrong type, that is
       functions that do not return a unit value. Two possibilities:
       -- change ``iter f'' into ``iter (function x -> f x; ())'' or better
          use ``iter (function x -> let _ = f x in ())'' that
          explicitly throws away the result of f.
       -- define a new function that returns unit (the pure
       side-effect part of the old function) and iter that new
       function. In many cases, this is clearer and may be more
       efficient. It is also reminiscent of having two functionals for
       iteration on lists: one for computations (meaningful results)
       that is map, one for side-effects only List.iter.

That's all what you have to do.

> [...]
> % ~/usr/sparc-solaris/bin/ocamlc -c caml_map.mli
> % ~/usr/sparc-solaris/bin/ocamlc -c caml_map.ml
> The implementation caml_map.ml does not match the interface caml_map.cmi:
> Values do not match:
>   val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
> is not included in
>   val iter : ('a -> 'b -> 'c) -> ('a, 'b) t -> unit

Nothing strange here, this is a regular typechecking sanity check.

> [...]
> From caml_map.mli:
> ---------------------------------------------------------------------------
> val iter: ('a -> 'b -> 'c) -> ('a, 'b) t -> unit
> ---------------------------------------------------------------------------
> 
> From caml_map.ml:
> ---------------------------------------------------------------------------
> let iter f m =
>   let rec iter = function
>     Empty -> ()
>   | Node(l, b, r, _) ->
>       iter l;
>       f b.key b.data;
>       List.iter (f b.key) b.prev;
>       iter r
>   in iter m.tree;;
> ---------------------------------------------------------------------------
> Paul Stodghill <stodghil@cs.cornell.edu>
> http://www.cs.cornell.edu/home/stodghil/home.html

Nothing strange as well: the line

>       List.iter (f b.key) b.prev;

constraints f to have a unit target type. Hence Caml_map.iter gets
type ('a -> 'b -> unit) -> ('a, 'b) t -> unit. Hence the mismatch with
the declared interface.

You just have to change the interface, according to the more accurate
type for iteration functions. In interface caml_map.mli, declare iter
with the appropriate type:

 val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit

Best regards,

Pierre Weis

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







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

* Re: Type-checking bug (or feature?) in O'Caml 1.06
  1997-11-18 19:05 ` Paul Stodghill
@ 1997-11-19  9:39   ` Pierre Weis
  0 siblings, 0 replies; 4+ messages in thread
From: Pierre Weis @ 1997-11-19  9:39 UTC (permalink / raw)
  To: Paul Stodghill; +Cc: caml-list

> The new behavior is even more bizarre than I had first thought.
> 
> ---------------------------------------------------------------------------
> % cat foo.mli
> type ('a, 'b) t;;
> val iter: ('a -> 'b -> 'unit) -> ('a, 'b) t -> unit
[...]
> % ocamlc -v -i -c foo.mli
> [...]
> val iter : ('a -> 'b -> 'c) -> ('a, 'b) t -> unit
> 
> Why is the generated type different than the declared type?

It is not, since you declared iter with the same type scheme:

> val iter: ('a -> 'b -> 'unit) -> ('a, 'b) t -> unit
                         ^

the ' symbole turns out 'unit to be a type variable. Free variables
<I>names</I> in type schemes are irrelevant (as for functions
abstracted arguments in programs). Thus, in its messages, the compiler
generates new names for type variables as 'a, 'b, 'c, ..., and
the original names written in the source programs are forgotten.
For instance:

# type ('key, 'assoc_val) t = ('key * 'assoc_val) list;;
type ('a, 'b) t = ('a * 'b) list

Thus, the declared type scheme and the generated type scheme are equivalent.

Best regards,

Pierre Weis

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







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

end of thread, other threads:[~1997-11-19  9:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-11-18 18:57 Type-checking bug (or feature?) in O'Caml 1.06 Paul Stodghill
1997-11-18 19:05 ` Paul Stodghill
1997-11-19  9:39   ` Pierre Weis
1997-11-19  9:24 ` Pierre Weis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox