* [Caml-list] Cyclic ?!
@ 2002-08-15 2:19 Oleg
2002-08-15 14:31 ` Michael Hicks
2002-08-18 16:13 ` [Caml-list] Cyclic ?! John Max Skaller
0 siblings, 2 replies; 7+ messages in thread
From: Oleg @ 2002-08-15 2:19 UTC (permalink / raw)
To: caml-list
Hi
I'm puzzled by the following compiler behavior:
If I define bin_tree as
type 'a bin_tree =
Empty
| Node of 'a bin_tree * 'a * 'a bin_tree
the compiler accepts it. OTOH if I define it as
type 'a bin_tree = ('a bin_tree * 'a * 'a bin_tree) option
It gives an error: "The type abbreviation bin_tree is cyclic".
Why??? And what's the difference between the two, really?
Thanks
Oleg
-------------------
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] 7+ messages in thread
* RE: [Caml-list] Cyclic ?!
2002-08-15 2:19 [Caml-list] Cyclic ?! Oleg
@ 2002-08-15 14:31 ` Michael Hicks
2002-08-15 17:26 ` Oleg
2002-08-18 16:13 ` [Caml-list] Cyclic ?! John Max Skaller
1 sibling, 1 reply; 7+ messages in thread
From: Michael Hicks @ 2002-08-15 14:31 UTC (permalink / raw)
To: 'Oleg', caml-list
If memory serves, ML datatypes elegantly overload about three distrinct
type-theoretic constructs. In particular, the variant tags in the data
type definition double as the "witnesses" to coercions between an
iso-recursive type and its "unrolling" of one level. Without going into
detail, this is why you can define something like
type foo = Rec of foo;;
but you can't define
type foo = foo;;
The latter definition is in the style of "equi-recursive" types, in
which a recursive type is equivalent any number of its unrollings. This
formulation is harder to typecheck, as I recall. There is a similar
analogy between the two definitions of bin_tree that you present.
Mike
-----Original Message-----
From: owner-caml-list@pauillac.inria.fr
[mailto:owner-caml-list@pauillac.inria.fr] On Behalf Of Oleg
Sent: Wednesday, August 14, 2002 10:20 PM
To: caml-list@inria.fr
Subject: [Caml-list] Cyclic ?!
Hi
I'm puzzled by the following compiler behavior:
If I define bin_tree as
type 'a bin_tree =
Empty
| Node of 'a bin_tree * 'a * 'a bin_tree
the compiler accepts it. OTOH if I define it as
type 'a bin_tree = ('a bin_tree * 'a * 'a bin_tree) option
It gives an error: "The type abbreviation bin_tree is cyclic".
Why??? And what's the difference between the two, really?
Thanks
Oleg
-------------------
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
-------------------
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] 7+ messages in thread
* Re: [Caml-list] Cyclic ?!
2002-08-15 14:31 ` Michael Hicks
@ 2002-08-15 17:26 ` Oleg
2002-08-15 18:05 ` Markus Mottl
2002-09-24 16:23 ` [Caml-list] Recursive types (Was Cyclic ?!) Christophe Raffalli
0 siblings, 2 replies; 7+ messages in thread
From: Oleg @ 2002-08-15 17:26 UTC (permalink / raw)
To: Michael Hicks, caml-list
Hi
I'm not sure I understand you. If the two definitions are equivalent WRT
Empty <-> None & Node <-> Some name substitution, then the fact that the
compiler accepts one, but not the other must be a bug, yes?
Regards
Oleg
On Thursday 15 August 2002 10:31 am, Michael Hicks wrote:
> If memory serves, ML datatypes elegantly overload about three distrinct
> type-theoretic constructs. In particular, the variant tags in the data
> type definition double as the "witnesses" to coercions between an
> iso-recursive type and its "unrolling" of one level. Without going into
> detail, this is why you can define something like
>
> type foo = Rec of foo;;
>
> but you can't define
>
> type foo = foo;;
>
> The latter definition is in the style of "equi-recursive" types, in
> which a recursive type is equivalent any number of its unrollings. This
> formulation is harder to typecheck, as I recall. There is a similar
> analogy between the two definitions of bin_tree that you present.
>
> Mike
>
> -----Original Message-----
> From: owner-caml-list@pauillac.inria.fr
> [mailto:owner-caml-list@pauillac.inria.fr] On Behalf Of Oleg
> Sent: Wednesday, August 14, 2002 10:20 PM
> To: caml-list@inria.fr
> Subject: [Caml-list] Cyclic ?!
>
> Hi
>
> I'm puzzled by the following compiler behavior:
>
> If I define bin_tree as
>
> type 'a bin_tree =
> Empty
>
> | Node of 'a bin_tree * 'a * 'a bin_tree
>
> the compiler accepts it. OTOH if I define it as
>
> type 'a bin_tree = ('a bin_tree * 'a * 'a bin_tree) option
>
> It gives an error: "The type abbreviation bin_tree is cyclic".
> Why??? And what's the difference between the two, really?
>
> Thanks
> Oleg
> -------------------
> 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
-------------------
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] 7+ messages in thread
* Re: [Caml-list] Cyclic ?!
2002-08-15 17:26 ` Oleg
@ 2002-08-15 18:05 ` Markus Mottl
2002-08-15 18:16 ` Brian Smith
2002-09-24 16:23 ` [Caml-list] Recursive types (Was Cyclic ?!) Christophe Raffalli
1 sibling, 1 reply; 7+ messages in thread
From: Markus Mottl @ 2002-08-15 18:05 UTC (permalink / raw)
To: Oleg; +Cc: Michael Hicks, caml-list
On Thu, 15 Aug 2002, Oleg wrote:
> I'm not sure I understand you. If the two definitions are equivalent WRT
> Empty <-> None & Node <-> Some name substitution, then the fact that the
> compiler accepts one, but not the other must be a bug, yes?
This is not a bug, because you can have the compiler typecheck it using
the command-line flag "-rectypes".
You'll certainly want to know now why this isn't standard behaviour.
Type inference of recursive types is actually neither a theoretical
problem nor an implementation difficulty (basically, I think, you just
need to drop the occurs check during type unification - please correct
me if I'm wrong).
The problem rather is that programmers can accidently write down
meaningless expressions for which the compiler infers absolutely crazy
types. If I remember correctly, OCaml already had the more general rule
by default in some ancient version, but the developers found that this
generality caused more confusion than benefits to programmers...
Regards,
Markus Mottl
--
Markus Mottl markus@oefai.at
Austrian Research Institute
for Artificial Intelligence http://www.oefai.at/~markus
-------------------
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] 7+ messages in thread
* Re: [Caml-list] Cyclic ?!
2002-08-15 18:05 ` Markus Mottl
@ 2002-08-15 18:16 ` Brian Smith
0 siblings, 0 replies; 7+ messages in thread
From: Brian Smith @ 2002-08-15 18:16 UTC (permalink / raw)
To: caml-list
Hi,
Markus Mottl wrote:
> On Thu, 15 Aug 2002, Oleg wrote:
>
>>I'm not sure I understand you. If the two definitions are equivalent WRT
>>Empty <-> None & Node <-> Some name substitution, then the fact that the
>>compiler accepts one, but not the other must be a bug, yes?
>
> This is not a bug, because you can have the compiler typecheck it using
> the command-line flag "-rectypes".
>
> The problem rather is that programmers can accidently write down
> meaningless expressions for which the compiler infers absolutely crazy
> types. If I remember correctly, OCaml already had the more general rule
> by default in some ancient version, but the developers found that this
> generality caused more confusion than benefits to programmers...
But, if this is the case, then wouldn't that still apply to other parts
of a program using recursive types? In other words, if I use one
recursive type, then I must use -rectypes, but that means that the
"extra strict checking" that O'Caml normally does won't help me in the
rest of my program, where I might use recursive types accidently and
thus cause O'Caml to infer "absolutely crazy types".
I think, instead of a command-line option, it would be better to provide
a syntactical annotation on each type definition where this behavior is
desired. That way, the default strict checking would always apply, but
it can be overridden by somebody that knows they really really want a
recursive type.
What do you think?
- 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] 7+ messages in thread
* Re: [Caml-list] Cyclic ?!
2002-08-15 2:19 [Caml-list] Cyclic ?! Oleg
2002-08-15 14:31 ` Michael Hicks
@ 2002-08-18 16:13 ` John Max Skaller
1 sibling, 0 replies; 7+ messages in thread
From: John Max Skaller @ 2002-08-18 16:13 UTC (permalink / raw)
To: Oleg; +Cc: caml-list
Oleg wrote:
> Hi
>
> I'm puzzled by the following compiler behavior:
>
> If I define bin_tree as
>
> type 'a bin_tree =
> Empty
> | Node of 'a bin_tree * 'a * 'a bin_tree
>
> the compiler accepts it. OTOH if I define it as
>
> type 'a bin_tree = ('a bin_tree * 'a * 'a bin_tree) option
>
> It gives an error: "The type abbreviation bin_tree is cyclic".
> Why??? And what's the difference between the two, really?
No semantic difference at all.
But there is a syntactic difference:
ocaml (without -rectypes) only allows cycles across
"object boundaries", that includes across variant
constructor names.
In the 'option' case,
the constructor name in 'option' type (namely "Some")
isn't explicitly separating the LHS and RHS parts of
the declaration. The syntax checker doesn't know
what 'option' is yet, it's just an arbitrary
polymorphic type: it could be:
type 'a option = 'a
in which case, there really is an error.
Note that a polymorphic type (like option)
could be abstract -- in which case we
don't know it's internals, and there is no
choice but to reject the above style
in that case (assuming we want to enforce the
'no recursion except across object boundaries' rule).
So it seems the check is done *before* the lookup
for the meaning of 'option' which is why
I called it a 'syntax check' -- it is based
entirely on the shape of the declaration
in the abstract -- without considering the meaning
of the subterms.
This makes the rule robust in the face of
substitution (changing 'option' to 'id' for
example, where 'a id = 'a)
--
John Max Skaller, mailto:skaller@ozemail.com.au
snail:10/1 Toxteth Rd, Glebe, NSW 2037, Australia.
voice:61-2-9660-0850
-------------------
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] 7+ messages in thread
* [Caml-list] Recursive types (Was Cyclic ?!)
2002-08-15 17:26 ` Oleg
2002-08-15 18:05 ` Markus Mottl
@ 2002-09-24 16:23 ` Christophe Raffalli
1 sibling, 0 replies; 7+ messages in thread
From: Christophe Raffalli @ 2002-09-24 16:23 UTC (permalink / raw)
To: caml-list
Note: there is a nice exercise at the end of the mail ...
There is a better solution then -rectypes that the developper could
implement :
Let the us write recursive type annotation in programs, but
when doing the loop detection in the unification used by the
type-checker, each loop should go
through a type variable that has been created by one of these type
anotation.
So the only thing you have to add to the type-checker is a marker on
type variables introduced by the user: if the user write (e : ... as 'a)
then 'a is marked.
This mark is propagated by unification and the loop detection is
modified as I suggested.
Therefore, the type-checker will not introduce recursive types by itself
and the cost is not to much (I have in mind a unification algorithm
using graph unification followed by loop detection, I do not know if
this is what OCaml uses, but I guess it is).
--
By the way, here is a nice program using recursive types:
run l n where l is a list of functions from positive int to positive int
and n is a nat will produce a list of int of size n such that all the
functions in l are increasing on that list ...
The program prints the lists it tries before finding the good one.
Exercise: try to remove the need for -rectypes ... keeping the same
algorithm.
--
(* an algorithm extracted (by hand) from the proof of Dickson's lemma *)
(* by C. Raffalli *)
(* compile with ocamlc -rectypes *)
let lem1 f e k =
let rec k' x q = k (x : int) ((f,k')::q) in
e k'
let lem2 f u x = lem1 f (u (x : int))
let rec dickson lf =
match lf with
[] -> (fun x k -> k x [])
| f::lf -> lem2 f (dickson lf)
let rec extract n u k =
match n with
0 -> k []
| x ->
let k' l =
match l with
[] -> u 0 (fun x lx -> k [x,lx])
| (y, ly)::_ -> u (y+1) (fun z lz -> k ((z,lz)::l))
in
extract (x - 1) u k'
let weak_dickson lf n = extract n (dickson lf)
let rec decidable' acc = function
(y, (ly : (((int -> int) * (int -> 'a -> 'c)) list as 'a)))::l ->
match l with
[] -> y::acc
| (x,(lx : 'a))::_ ->
let rec test lx' ly' =
match lx', ly' with
[], [] -> decidable' (y::acc) l
| (((fx : int -> int),( kx : int -> 'a -> 'c))::lx'), (((fy : int ->
int), (ky : int -> 'a -> 'c))::ly') ->
if not (fx == fy) then failwith "bug: the function should be the same !";
if fx x < fx y then
ky x lx' else test lx' ly'
in test lx ly
let print_list f l =
List.iter (fun x -> print_int (f x); print_string ", ") l;
print_newline ()
let count = ref 0
let reset () =
print_string "Number of tries:"; print_int !count; print_newline ();
count := 0
let decidable l =
print_list fst l;
incr count;
decidable' [] l;
let run l n =
let r = weak_dickson l n decidable in
reset ();
r
--
--
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
-------------------
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] 7+ messages in thread
end of thread, other threads:[~2002-09-25 7:09 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-15 2:19 [Caml-list] Cyclic ?! Oleg
2002-08-15 14:31 ` Michael Hicks
2002-08-15 17:26 ` Oleg
2002-08-15 18:05 ` Markus Mottl
2002-08-15 18:16 ` Brian Smith
2002-09-24 16:23 ` [Caml-list] Recursive types (Was Cyclic ?!) Christophe Raffalli
2002-08-18 16:13 ` [Caml-list] Cyclic ?! John Max Skaller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox