* [Caml-list] recursive modules redux, & interface files @ 2001-03-18 23:05 Chris Hecker 2001-03-19 0:01 ` Brian Rogoff ` (2 more replies) 0 siblings, 3 replies; 36+ messages in thread From: Chris Hecker @ 2001-03-18 23:05 UTC (permalink / raw) To: caml-list Two questions/problems: 1. So, I understand that doing recursive types across modules is hard (but I'd say very important for decoupling large software), but is it true that I can't even call across modules recursively? Even with mli files to resolve the types? I find that incredibly hard to believe, but I can't get it to work and it seems the docs say it's impossible as well (so why am I posting about it, you ask? Disbelief that it's not possible, I guess. :). What is the point of separate mli files if they can't be used to declare a callable interface separate from the implementation? Is this just a small feature that needs to be added to the linker (defer binding unseen modules until all the object files have been seen), or is there something really subtle going on? Since everything compiles and type checks fine, and the subtleties that I don't understand in ocaml usually have to do with the type checker, I'm having trouble seeing how this could be that hard. Example below. Am I missing something? 2. Also, on a related note, why do the interface file and the implementation file (or equivalently, I believe, the signature and structure) both have to have all the concrete types duplicated? I can see the value of having interfaces that hide some implementation stuff and abstract types, but if I've got a big fully-specified variant type in a .mli file, it's annoying and error prone (yes, I know the compiler will catch it) to have to retype the whole thing into the ml file (which I have to do if I want to hide anything else in the ml file, meaning I can't just have an ml without an mli). Is this something the "include" keyword takes care of? Heck, "#include<foo.mli>" would be an improvement over duplicating all the types. :) One of the things I hate about C++ and is having to type function declarations/definitions multiple times. Thanks, Chris --------- Example for Question 1: --- t1.mli --- val foo: int -> int --- t1.ml --- let foo x = if x = 1 then T2.bar x else x --- t2.mli --- val bar: int -> int --- t2.ml --- let bar x = if x = 2 then T1.foo (x-1) else x --- main.ml --- let _ = print_int (T2.bar 2) ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-18 23:05 [Caml-list] recursive modules redux, & interface files Chris Hecker @ 2001-03-19 0:01 ` Brian Rogoff 2001-03-19 11:04 ` John Max Skaller 2001-03-21 18:41 ` Xavier Leroy 2 siblings, 0 replies; 36+ messages in thread From: Brian Rogoff @ 2001-03-19 0:01 UTC (permalink / raw) To: caml-list On Sun, 18 Mar 2001, Chris Hecker wrote: > Two questions/problems: Just one answer/solution I'm afraid, but I also give a grotesque workaround... > 2. Also, on a related note, why do the interface file and the > implementation file (or equivalently, I believe, the signature and > structure) both have to have all the concrete types duplicated? I can > see the value of having interfaces that hide some implementation stuff > and abstract types, but if I've got a big fully-specified variant type > in a .mli file, it's annoying and error prone (yes, I know the compiler > will catch it) to have to retype the whole thing into the ml file > (which I have to do if I want to hide anything else in the ml file, meaning I > can't just have an ml without an mli). Is this something the > "include" keyword takes care of? No, but if you are finding this really onerous then you can use "open" by creating a "pure" mli file with your gignatic variant type and opening it in the mli and ml file where it is needed. Does that help? -- Brian PS : There are some ways to get around the fact that the linker requires ordering, either by putting the mutually recursive functions in the same module (I assume you know this) or by breaking the cycle with an indirection (first rule of programming: any problem can be solved with another level of indirection :-). In this case, the indirection can be provided by passing in functions to foo and bar. Yeah, it's ugly and all that but it is a workaround. (* t1.mli *) val foo : (int -> int) -> int -> int (* t2.mli *) val bar: (int -> int) -> int -> int (* t1.ml *) let foo f x = if x = 1 then f x else x (* t2.ml *) let bar f x = if x = 2 then f (x-1) else x (* main.ml *) let rec foo_aux x = T2.bar bar_aux x and bar_aux x = T1.foo foo_aux x let _ = print_int (T2.bar bar_aux 2) ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-18 23:05 [Caml-list] recursive modules redux, & interface files Chris Hecker 2001-03-19 0:01 ` Brian Rogoff @ 2001-03-19 11:04 ` John Max Skaller 2001-03-19 11:41 ` Chris Hecker 2001-03-22 11:40 ` Markus Mottl 2001-03-21 18:41 ` Xavier Leroy 2 siblings, 2 replies; 36+ messages in thread From: John Max Skaller @ 2001-03-19 11:04 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list Chris Hecker wrote: > > Two questions/problems: > > 1. So, I understand that doing recursive types across modules is hard (but I'd say very important for decoupling large software), but is it true that I can't even call across modules recursively? Yes. More precisely, you cannot forward reference any symbol, however you _can_ call forward by passing a function backward as an argument. [This sucks though] > 2. Also, on a related note, why do the interface file and the implementation file (or equivalently, I believe, the signature and structure) both have to have all the concrete types duplicated? Because types in a given implementation may or may not be present in the interface. IF you have a file containing ONLY types, then there is no need to have an .ml file for it. If you have even one val (function, class), you need the .ml file. -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-19 11:04 ` John Max Skaller @ 2001-03-19 11:41 ` Chris Hecker 2001-03-20 17:43 ` John Max Skaller 2001-03-22 11:40 ` Markus Mottl 1 sibling, 1 reply; 36+ messages in thread From: Chris Hecker @ 2001-03-19 11:41 UTC (permalink / raw) To: John Max Skaller; +Cc: caml-list > Because types in a given implementation may or may not be present >in the interface. Right, that's fine, but I only want to have them once, whereever they are. So, if it's a private type, it's in the ml file, and if it's public it's in the mli file (assuming I want one, if I don't then everything's public). How does having them duplicated buy me anything but trouble? Chris ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-19 11:41 ` Chris Hecker @ 2001-03-20 17:43 ` John Max Skaller 2001-03-21 4:03 ` Chris Hecker 0 siblings, 1 reply; 36+ messages in thread From: John Max Skaller @ 2001-03-20 17:43 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list Chris Hecker wrote: > > > Because types in a given implementation may or may not be present > >in the interface. > > Right, that's fine, but I only want to have them once, whereever they are. So, if it's a private type, it's in the ml file, and if it's public it's in the mli file (assuming I want one, if I don't then everything's public). How does having them duplicated buy me anything but trouble? > > Chris In C++, a function is either extern or static. There are only two options. [And non-local classes are _always_ extern] This is not so in Ocaml: you may wish to provide access to a component such as a function with a type more constrained than the actual implementation. For example: (* twoint.mli *) val twoint: int -> int * int (* twoint.ml *) let twoint x = (x,x) Here, the implementation is actually polymorphic, it will work for more than ints, but clients of the module 'twoint' cannot use this function to make a pair of floats. Here is another example: (* abstr.mli *) type t val get: t -> int val make: int -> t (* abstr.ml *) type t = int * int let get x = fst x let make x = (x,x+1) Here, the type t is implemented as a pair of ints. But the implementation is hidden from the client of the module. Note that the type 't' itself is not hidden. -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-20 17:43 ` John Max Skaller @ 2001-03-21 4:03 ` Chris Hecker 2001-03-21 5:10 ` Patrick M Doane ` (2 more replies) 0 siblings, 3 replies; 36+ messages in thread From: Chris Hecker @ 2001-03-21 4:03 UTC (permalink / raw) To: John Max Skaller; +Cc: Chris Hecker, caml-list > There are only two options. [And non-local classes are _always_ extern] > This is not so in Ocaml: you may wish to provide access to a component > such as a function with a type more constrained than the actual > implementation. Yes yes yes, I know this. I'm saying I understand why I need to type stuff if there's a difference betwen the .ml and .mli versions (hiding stuff, restricting stuff, abstracting stuff), and that's fine. I'm asking why I need to retype stuff if it's identical. Check out some of the source code in the compiler, or any ocaml project I've seen (the ICFP winners, whatever). There are tons of really huge variants that are just duplicated in mli and ml. That seems bad, for the same reason that typing a C++ function declaration 2 times is bad. Chris ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 4:03 ` Chris Hecker @ 2001-03-21 5:10 ` Patrick M Doane 2001-03-21 9:27 ` Chris Hecker ` (2 more replies) 2001-03-21 18:18 ` John Max Skaller 2001-03-21 18:19 ` John Max Skaller 2 siblings, 3 replies; 36+ messages in thread From: Patrick M Doane @ 2001-03-21 5:10 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list I agree that checking interface/implementation of modules could be improved. For projects that I've worked on that have huge variant types, I have typically placed the variants in a module by themselves with no .mli file. This technique hasn't worked too well for me in practice and is still annoying for the smaller variants. A reasonable modification to the language would allow a module expression to not include type definitions when they are defined in the module type and include their type information. This would mean that module X : sig type t = int end = struct end would be accepted, but module X : sig type t end = struct end would be rejected because the abstract field 't' is required but missing. Would this proposal address all the issues you had in mind? Patrick Doane On Tue, 20 Mar 2001, Chris Hecker wrote: > > > There are only two options. [And non-local classes are _always_ extern] > > This is not so in Ocaml: you may wish to provide access to a component > > such as a function with a type more constrained than the actual > > implementation. > > Yes yes yes, I know this. I'm saying I understand why I need to type > stuff if there's a difference betwen the .ml and .mli versions (hiding > stuff, restricting stuff, abstracting stuff), and that's fine. I'm > asking why I need to retype stuff if it's identical. Check out some > of the source code in the compiler, or any ocaml project I've seen > (the ICFP winners, whatever). There are tons of really huge variants > that are just duplicated in mli and ml. That seems bad, for the same > reason that typing a C++ function declaration 2 times is bad. > > Chris > > > ------------------- > To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr > ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 5:10 ` Patrick M Doane @ 2001-03-21 9:27 ` Chris Hecker 2001-03-21 18:20 ` John Max Skaller 2001-03-21 23:24 ` John Prevost 2 siblings, 0 replies; 36+ messages in thread From: Chris Hecker @ 2001-03-21 9:27 UTC (permalink / raw) To: Patrick M Doane; +Cc: caml-list > This would mean that > module X : sig type t = int end = struct end > would be accepted, but > module X : sig type t end = struct end > would be rejected because the abstract field 't' is required but missing. > Would this proposal address all the issues you had in mind? Yep, that's what I had in mind! Chris ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 5:10 ` Patrick M Doane 2001-03-21 9:27 ` Chris Hecker @ 2001-03-21 18:20 ` John Max Skaller 2001-03-22 0:03 ` Patrick M Doane 2001-03-21 23:24 ` John Prevost 2 siblings, 1 reply; 36+ messages in thread From: John Max Skaller @ 2001-03-21 18:20 UTC (permalink / raw) To: Patrick M Doane; +Cc: Chris Hecker, caml-list Patrick M Doane wrote: > For projects that I've worked on that have huge variant types, I have > typically placed the variants in a module by themselves with no .mli file. > This technique hasn't worked too well for me in practice and is still > annoying for the smaller variants. Try placing them in a .mli file instead (no ml file). -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 18:20 ` John Max Skaller @ 2001-03-22 0:03 ` Patrick M Doane 2001-03-22 0:22 ` Brian Rogoff 2001-03-22 9:11 ` [Caml-list] recursive modules redux, & interface files Francois Pottier 0 siblings, 2 replies; 36+ messages in thread From: Patrick M Doane @ 2001-03-22 0:03 UTC (permalink / raw) To: John Max Skaller; +Cc: caml-list I don't see that it makes much of a difference. Besides, the reason it hasn't worked well for me is that inevitably I want to add some functions to the module that has the variant type. For example, pretty printers. The next compromise is to continue the path without a .mli file until I don't want some of these utilities to be exported. In the end, I'm back to the source of the problem, having to duplicate a large variant type. On Thu, 22 Mar 2001, John Max Skaller wrote: > Patrick M Doane wrote: > > > For projects that I've worked on that have huge variant types, I have > > typically placed the variants in a module by themselves with no .mli file. > > This technique hasn't worked too well for me in practice and is still > > annoying for the smaller variants. > > Try placing them in a .mli file instead (no ml file). > > -- > John (Max) Skaller, mailto:skaller@maxtal.com.au > 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 > checkout Vyper http://Vyper.sourceforge.net > download Interscript http://Interscript.sourceforge.net > ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 0:03 ` Patrick M Doane @ 2001-03-22 0:22 ` Brian Rogoff 2001-03-22 10:26 ` [Caml-list] duplication implementation/interface Judicael Courant 2001-03-22 9:11 ` [Caml-list] recursive modules redux, & interface files Francois Pottier 1 sibling, 1 reply; 36+ messages in thread From: Brian Rogoff @ 2001-03-22 0:22 UTC (permalink / raw) To: Patrick M Doane; +Cc: John Max Skaller, caml-list On Wed, 21 Mar 2001, Patrick M Doane wrote: > I don't see that it makes much of a difference. Besides, the reason it > hasn't worked well for me is that inevitably I want to add some > functions to the module that has the variant type. For example, pretty > printers. The next compromise is to continue the path without a .mli file > until I don't want some of these utilities to be exported. In the end, > I'm back to the source of the problem, having to duplicate a large variant > type. What's the problem with the hack I suggested earlier: put the huge variant (and other duplicated types) in a "pure" .mli file (I hate using .ml for that) and "open"ing it where you need it, once in the .mli file and once in the .ml file? This way you reduce the duplication to two lines. I know some people are open-phobes, but I find this use of open to be acceptable. -- Brian > > On Thu, 22 Mar 2001, John Max Skaller wrote: > > > Patrick M Doane wrote: > > > > > For projects that I've worked on that have huge variant types, I have > > > typically placed the variants in a module by themselves with no .mli file. > > > This technique hasn't worked too well for me in practice and is still > > > annoying for the smaller variants. > > > > Try placing them in a .mli file instead (no ml file). > > > > -- > > John (Max) Skaller, mailto:skaller@maxtal.com.au > > 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 > > checkout Vyper http://Vyper.sourceforge.net > > download Interscript http://Interscript.sourceforge.net > > > > ------------------- > To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr > ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] duplication implementation/interface 2001-03-22 0:22 ` Brian Rogoff @ 2001-03-22 10:26 ` Judicael Courant 2001-03-22 11:16 ` [Caml-list] about typedefs... (was: duplication implementation/interface) Olivier Andrieu 2001-03-22 17:14 ` [Caml-list] duplication implementation/interface Brian Rogoff 0 siblings, 2 replies; 36+ messages in thread From: Judicael Courant @ 2001-03-22 10:26 UTC (permalink / raw) To: Brian Rogoff; +Cc: caml-list Brian Rogoff a écrit : > [...] > What's the problem with the hack I suggested earlier: put the huge variant > (and other duplicated types) in a "pure" .mli file (I hate using .ml for > that) and "open"ing it where you need it, once in the .mli file and once in the > .ml file? This way you reduce the duplication to two lines. > > I know some people are open-phobes, but I find this use of open to be > acceptable. > As for open-phobes, somebody gave me a good solution a few days ago: you can locally define a module with a very short name. Example : put your type in my_beautiful_type.mli with constructors Node, Leaf, ..., and where you need it do module T = My_beautiful_type then you can use it with a small overhead of 2 chars per use of a constructor of My_beautiful_type: T.Node, T.Leaf, ... This is quite elegant IMHO as it makes your code very clear. As an aside, if you consider applying the same treatment for exceptions (also duplicated), you need to put them in a .ml file (not a .mli) as a .cmo is needed for linking (an exception actually creates at run-time a fresh exception identifier). Judicaël -- Judicael.Courant@lri.fr, http://www.lri.fr/~jcourant/ (+33) (0)1 69 15 64 85 "Montre moi des morceaux de ton monde, et je te montrerai le mien" Tim, matricule #929, condamné à mort. http://rozenn.picard.free.fr/tim.html ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] about typedefs... (was: duplication implementation/interface) 2001-03-22 10:26 ` [Caml-list] duplication implementation/interface Judicael Courant @ 2001-03-22 11:16 ` Olivier Andrieu 2001-03-22 17:14 ` [Caml-list] duplication implementation/interface Brian Rogoff 1 sibling, 0 replies; 36+ messages in thread From: Olivier Andrieu @ 2001-03-22 11:16 UTC (permalink / raw) To: caml-list Judicael Courant [Thursday 22 March 2001] : > Brian Rogoff a écrit : > > > [...] > > What's the problem with the hack I suggested earlier: put the > > huge variant (and other duplicated types) in a "pure" .mli file > > (I hate using .ml for that) and "open"ing it where you need it, > > once in the .mli file and once in the .ml file? This way you > > reduce the duplication to two lines. > > > > I know some people are open-phobes, but I find this use of open > > to be acceptable. > > > > As for open-phobes, somebody gave me a good solution a few days > ago: you can locally define a module with a very short name. There's something I've been wondering about type definitions : In type definitions, you can specify type equation and representation. - when none is specified, the defined type is abstract ; - when an equation is given, you get an alias of an already existing type ; - with a representation, a new variant or record is defined. But it is possible to use both, so that you get an alias of an already defined variant and record but with the fields or constructors attached to the new type. It don't really see the point of such a definition : now the type representation is in 4 different places, and the only gain I see is that you don't have to prefix the fields names with a module path. That's no big deal since you can redefine the module with a short name (one letter). So, is this form of type definitions actually used, does it have another purpose besides this namespace issue ? Olivier ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] duplication implementation/interface 2001-03-22 10:26 ` [Caml-list] duplication implementation/interface Judicael Courant 2001-03-22 11:16 ` [Caml-list] about typedefs... (was: duplication implementation/interface) Olivier Andrieu @ 2001-03-22 17:14 ` Brian Rogoff 1 sibling, 0 replies; 36+ messages in thread From: Brian Rogoff @ 2001-03-22 17:14 UTC (permalink / raw) To: Judicael Courant; +Cc: caml-list [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: TEXT/PLAIN; charset=X-UNKNOWN, Size: 2261 bytes --] On Thu, 22 Mar 2001, Judicael Courant wrote: > Brian Rogoff a écrit : > > > [...] > > What's the problem with the hack I suggested earlier: put the huge variant > > (and other duplicated types) in a "pure" .mli file (I hate using .ml for > > that) and "open"ing it where you need it, once in the .mli file and once in the > > .ml file? This way you reduce the duplication to two lines. > > > > I know some people are open-phobes, but I find this use of open to be > > acceptable. > > > > As for open-phobes, somebody gave me a good solution a few days ago: you > can locally define a module with a very short name. > > Example : put your type in my_beautiful_type.mli with constructors Node, > Leaf, ..., and where you need it do > > module T = My_beautiful_type > > then you can use it with a small overhead of 2 chars per use of a > constructor of My_beautiful_type: T.Node, T.Leaf, ... > > This is quite elegant IMHO as it makes your code very clear. Oh yes, this is the common solution in Ada-land for "use-phobes" (their analogue of open-phobes :) to long package names. They have it a little better in that "use" can be in any declarative region so it makes it easier to find which module things come from. It is possible to do this in OCaml with the local module feature but I don't see it as much in code I've read. > As an aside, if you consider applying the same treatment for exceptions > (also duplicated), you need to put them in a .ml file (not a .mli) as a > .cmo is needed for linking (an exception actually creates at run-time a > fresh exception identifier). Excellent point. However, I don't tend to define that many exceptions, far fewer than the size of variant types (which easily get tens of constructors even for a single type) so that duplication doesn't bother me as much as for types. Still, I should perhaps rethink my aversion to using a ".ml" as the file holding the duplicated info. This entire discussion has the seeds of a few more FAQ entries. Is our esteemed erstwhile moderator going to do it, or should I take a stab and then mail it along? -- Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 0:03 ` Patrick M Doane 2001-03-22 0:22 ` Brian Rogoff @ 2001-03-22 9:11 ` Francois Pottier 1 sibling, 0 replies; 36+ messages in thread From: Francois Pottier @ 2001-03-22 9:11 UTC (permalink / raw) To: Patrick M Doane; +Cc: caml-list On Wed, Mar 21, 2001 at 07:03:55PM -0500, Patrick M Doane wrote: > > I'm back to the source of the problem, having to duplicate a large variant > type. I think you have missed the point of John's (or was it Brian's?) suggestion, which is to place large type (or module type) definitions in a separate .mli (or .ml) file, then refer to it from your .mli *and* your .ml file. This has the unfortunate consequence of breaking every module into three files (shared definitions, interface, and implementations), making the program structure somewhat more cryptic. But it usually works well. Regarding your suggestion, > For every module definition M that has a signature S > For every type definition t in S that contains optional > type-information and is not defined in M > Add the type definition of t to M (preserving the order from S) ^^^^^^^^^^^^^^^^^^^^ I think the problematic part is in the ordering. The order in which bindings appear may be different in M and S, to start with. So, where do we insert the definition, and (assuming we know where) what do we do if some names referred to by the definition aren't yet defined in M at that point? -- François Pottier Francois.Pottier@inria.fr http://pauillac.inria.fr/~fpottier/ ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 5:10 ` Patrick M Doane 2001-03-21 9:27 ` Chris Hecker 2001-03-21 18:20 ` John Max Skaller @ 2001-03-21 23:24 ` John Prevost 2001-03-22 0:00 ` Patrick M Doane 2 siblings, 1 reply; 36+ messages in thread From: John Prevost @ 2001-03-21 23:24 UTC (permalink / raw) To: Patrick M Doane; +Cc: Chris Hecker, caml-list >>>>> "pd" == Patrick M Doane <patrick@watson.org> writes: pd> This would mean that pd> module X : sig type t = int end = struct end pd> would be accepted, but pd> module X : sig type t end = struct end pd> would be rejected because the abstract field 't' is required pd> but missing. What about "module X : sig type t end = struct type t end", where values of the type can't actually be constructed? (Except possibly by C code.) John. ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 23:24 ` John Prevost @ 2001-03-22 0:00 ` Patrick M Doane 0 siblings, 0 replies; 36+ messages in thread From: Patrick M Doane @ 2001-03-22 0:00 UTC (permalink / raw) To: John Prevost; +Cc: Chris Hecker, caml-list Hi John, It seems to me that this would be perfectly legal. It is accepted by the current Ocaml language, and by the extension I proposed unless there is something I'm missing. Is this the behavior you're expecting? Patrick On 21 Mar 2001, John Prevost wrote: > >>>>> "pd" == Patrick M Doane <patrick@watson.org> writes: > > pd> This would mean that > > pd> module X : sig type t = int end = struct end > > pd> would be accepted, but > > pd> module X : sig type t end = struct end > > pd> would be rejected because the abstract field 't' is required > pd> but missing. > > What about "module X : sig type t end = struct type t end", where > values of the type can't actually be constructed? (Except possibly by > C code.) > > John. > ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 4:03 ` Chris Hecker 2001-03-21 5:10 ` Patrick M Doane @ 2001-03-21 18:18 ` John Max Skaller 2001-03-21 18:19 ` John Max Skaller 2 siblings, 0 replies; 36+ messages in thread From: John Max Skaller @ 2001-03-21 18:18 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list Chris Hecker wrote: > > > There are only two options. [And non-local classes are _always_ extern] > > This is not so in Ocaml: you may wish to provide access to a component > > such as a function with a type more constrained than the actual > > implementation. > > Yes yes yes, I know this. I'm saying I understand why I need to type > stuff if there's a difference betwen the .ml and .mli versions (hiding > stuff, restricting stuff, abstracting stuff), and that's fine. I'm > asking why I need to retype stuff if it's identical. You don't. There is a tool: ocamlc -i fred.ml > fred.mli which will generate the mli file for you. (Use the -i option on the compiler). -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 4:03 ` Chris Hecker 2001-03-21 5:10 ` Patrick M Doane 2001-03-21 18:18 ` John Max Skaller @ 2001-03-21 18:19 ` John Max Skaller 2 siblings, 0 replies; 36+ messages in thread From: John Max Skaller @ 2001-03-21 18:19 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list Chris Hecker wrote: > > > There are only two options. [And non-local classes are _always_ extern] > > This is not so in Ocaml: you may wish to provide access to a component > > such as a function with a type more constrained than the actual > > implementation. > > Yes yes yes, I know this. I'm saying I understand why I need to type > stuff if there's a difference betwen the .ml and .mli versions (hiding > stuff, restricting stuff, abstracting stuff), and that's fine. I'm > asking why I need to retype stuff if it's identical. BTW: you DON'T actually need an .mli file. Try it. It is only needed when there IS a constraint on 'everything public'. -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-19 11:04 ` John Max Skaller 2001-03-19 11:41 ` Chris Hecker @ 2001-03-22 11:40 ` Markus Mottl 1 sibling, 0 replies; 36+ messages in thread From: Markus Mottl @ 2001-03-22 11:40 UTC (permalink / raw) To: John Max Skaller; +Cc: Chris Hecker, caml-list On Mon, 19 Mar 2001, John Max Skaller wrote: > Yes. More precisely, you cannot forward reference any symbol, > however you _can_ call forward by passing a function backward as an > argument. > [This sucks though] Note that you can always use local modules + functors so as not having to pass around functions backwards, e.g.: module MakeM (Spec : sig val f : int -> int end) = struct open Spec let foo x = f x let bar x y = f x + f y end let bla g = let module Spec = struct let f = g end in let module M = MakeM (Spec) in print_int (M.foo 42 + M.bar 1 2) let _ = bla succ Put the functions that should be "backwards parameterized" into functor "MakeM". Then generate its specifcation "Spec" at runtime in some function "bla" (here: "f" should be some function "g" passed at runtime) and apply the functor "MakeM" to the specification "Spec". Now you can access the "backwards parameterized" functions using the qualified module path "M." If you feel annoyed by the fully qualified path, just write another local module, in which you can "open" module "M" and provide some "start" function in this new module to continue execution. If you want even more hardcore moduling, you might be interested in trying out the new "include"-keyword for structures (my favourite new language extension! Thanks!) with the tricks above. You can do tremendous things with it, like overriding specific functions of modules at runtime, etc., with hardly any effort. The only remaining question here is: how efficiently can OCaml handle local modules and local functor applications? I haven't measured it, but I guess that this could be expensive. Regards, Markus Mottl -- Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-18 23:05 [Caml-list] recursive modules redux, & interface files Chris Hecker 2001-03-19 0:01 ` Brian Rogoff 2001-03-19 11:04 ` John Max Skaller @ 2001-03-21 18:41 ` Xavier Leroy 2001-03-22 0:23 ` Patrick M Doane ` (2 more replies) 2 siblings, 3 replies; 36+ messages in thread From: Xavier Leroy @ 2001-03-21 18:41 UTC (permalink / raw) To: Chris Hecker; +Cc: caml-list > 1. So, I understand that doing recursive types across modules is > hard (but I'd say very important for decoupling large software), but > is it true that I can't even call across modules recursively? Even > with mli files to resolve the types? I find that incredibly hard to > believe, but I can't get it to work and it seems the docs say it's > impossible as well (so why am I posting about it, you ask? > Disbelief that it's not possible, I guess. :). You're right that cross-module recursion even between functions is not supported, and you're right that this is not because of typing difficulties -- the type-checking of such recursions is easy. This is because value components of modules can be the result of arbitrary computations, and the only way to ensure that these computations succeed is by making sure they occur sequentially. Consider for instance: A.mli val x : int B.mli val y : int A.ml let x = B.y + 1 B.ml let y = A.x * 3 We don't know how to evaluate these definitions correctly -- indeed, there is no integer solution to this recursive definition. Other languages avoid this problem in one of two ways. C and C-like languages only allow global identifiers to be defined as functions or compile-time constants, but not results of arbitrary computations. Haskell and other lazy languages rely on lazy evaluation to perform on-demand initialization (i.e. compute the definition the first time it's needed), and aborting computation if a dynamic dependency cycle is detected (as in the example above). Java goes pretty much the Haskell way, relying on dynamic class loading to lazily evaluate static field definitions; originally, it raised an exception on discovering a dynamic dependency cycle; nowadays, I think it just pre-initializes static fields to 0 or null, then compute the initial values based on this (so that in the example above you'd get x = 1 and y = 3 if the program refers to B.y first, and y = 0 and x = 1 if the program refers to A.x first :-). The Haskell solution is semantically cleanest, but lazy evaluation of module components entails a performance penalty and some increase in code size (the compiler must emit "am I initialized already?" tests on every module value access). (The semantics of Java class initialization entail similar penalties, although they partially hide them by relying on JIT compilation -- blech.) A possible approach for Caml would be to have a link-time analysis that detects cross-module value recursions that involve only function definitions, and allow these (because they are safe -- like in C!). Fabrice Le Fessant posted a patch to OCaml a while ago that does pretty much this. I'm still hoping more general, principled solutions exist, but they sure are hard to design! > 2. Also, on a related note, why do the interface file and the > implementation file (or equivalently, I believe, the signature and > structure) both have to have all the concrete types duplicated? I can > see the value of having interfaces that hide some implementation stuff > and abstract types, but if I've got a big fully-specified variant type > in a .mli file, it's annoying and error prone (yes, I know the > compiler will catch it) to have to retype the whole thing into the ml > file (which I have to do if I want to hide anything else in the ml > file, meaning I can't just have an ml without an mli). Yes, it's annoying, and it's more or less a consequence of the ideology behind the ML module system: that structures define things, and that signatures can later be ascribed to these structures to hide or abstract some of these things. With this ideology, every type that is declared in a signature -- even if it's a concrete declaration that includes as much information as a type definition! -- must be matched by a type definition in the corresponding structure. It's just very principled and logical -- just a bit inconvenient at times :-) Another way to think about it is that every structure (or implementation file) must "stand on its own" and make sense without the signature (or interface file) that will be ascribed to it later on. It makes sense when the signature is not known when the structure is defined, e.g. module M = struct type t = A | B ... end (* 5000 lines later: *) module M' = (M : sig type t = A | B ... end) It becomes practically inconvenient when the signature is known at the time of the structure definition: module M : sig type t = A | B ... end = struct type t = A | B ... end Which is the case with interface and implementation files. In this case, one could envision an automatic completion of the structure / implementation file so that concrete type specifications from the signature do not need to be implemented in the structure. Doing this right is not obvious, though. First, it's not enough to say that a concrete type spec does not need to be matched in the structure. This would type-check module M : sig type t = A | B end = struct end but not module M : sig type t = A | B val v : t end = struct let v = A end In other terms, the unmatched concrete type specs in the signature need to be somehow reintroduced in the structure definition, so that other parts of the structure may refer to them. While I think it can be done in most practical cases, it's a bit of a kludge and I'm not sure how to do this in all cases. Is the practical value of this kludge enough to forget that it's a kludge? Can't we live with the current duplication of concrete type definitions in the name of systematic, principled module systems? I really don't know. Best, - Xavier Leroy ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 18:41 ` Xavier Leroy @ 2001-03-22 0:23 ` Patrick M Doane 2001-03-22 12:02 ` Hendrik Tews 2001-03-30 10:27 ` [Caml-list] parser combinators Kevin Backhouse 2 siblings, 0 replies; 36+ messages in thread From: Patrick M Doane @ 2001-03-22 0:23 UTC (permalink / raw) To: Xavier Leroy; +Cc: Chris Hecker, caml-list Hi Xavier, Your example demonstrates that a proposal for such an extension should be more explicit about how it should work. I had a particular implementation in mind from my post yesterday: For every module definition M that has a signature S For every type definition t in S that contains optional type-information and is not defined in M Add the type definition of t to M (preserving the order from S) Proceed with the usual algorithms for type checking, matching structures, etc. I think this should work properly. Anything I might have missed? You seem to elude to special cases that are not immediately obvious. I agree that it becomes kludgy to remove the separation that currently exists between structures and signatures. However, as a programmer maintaining the duplicate types also seems kludgy . After all, the compiler has the information available, why doesn't it use it? This seems to be a case where a compromise between theory and practice should be explored. Patrick On Wed, 21 Mar 2001, Xavier Leroy wrote: > It becomes practically inconvenient when the signature is known at the > time of the structure definition: > > module M : sig type t = A | B ... end = > struct type t = A | B ... end > > Which is the case with interface and implementation files. > > In this case, one could envision an automatic completion of the > structure / implementation file so that concrete type specifications > from the signature do not need to be implemented in the structure. > Doing this right is not obvious, though. First, it's not enough to > say that a concrete type spec does not need to be matched in the > structure. This would type-check > > module M : sig type t = A | B end = struct end > > but not > > module M : sig type t = A | B val v : t end = struct let v = A end > > In other terms, the unmatched concrete type specs in the signature > need to be somehow reintroduced in the structure definition, so that > other parts of the structure may refer to them. While I think it can > be done in most practical cases, it's a bit of a kludge and I'm not > sure how to do this in all cases. > > Is the practical value of this kludge enough to forget that it's a > kludge? Can't we live with the current duplication of concrete type > definitions in the name of systematic, principled module systems? > I really don't know. ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-21 18:41 ` Xavier Leroy 2001-03-22 0:23 ` Patrick M Doane @ 2001-03-22 12:02 ` Hendrik Tews 2001-03-22 13:01 ` Markus Mottl 2001-03-30 10:27 ` [Caml-list] parser combinators Kevin Backhouse 2 siblings, 1 reply; 36+ messages in thread From: Hendrik Tews @ 2001-03-22 12:02 UTC (permalink / raw) To: caml-list Hi, I would like to vote for solutions that work for the common case when writing large programs, even if they are hacks, considered from a theoretical point of view. Xavier Leroy writes: [cross module recursion] A.mli val x : int B.mli val y : int A.ml let x = B.y + 1 B.ml let y = A.x * 3 We don't know how to evaluate these definitions correctly -- indeed, there is no integer solution to this recursive definition. I think that in this case the theoretical cleaness is overrated. Cross module recursion of functions is soo useful, that it should be made to work --- even if the solution seems stupid with respect to the example above. [duplications in signatures and structures] Is the practical value of this kludge enough to forget that it's a kludge? Sure. Can't we live with the current duplication of concrete type definitions in the name of systematic, principled module systems? No, at least I cannot. Also here I would suggest to have a solution that works for the common case. What about changing include, such that including a signature into a structure includes all types and all exceptions? Bye, Hendrik ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 12:02 ` Hendrik Tews @ 2001-03-22 13:01 ` Markus Mottl 2001-03-22 16:56 ` Brian Rogoff 2001-03-27 8:21 ` Hendrik Tews 0 siblings, 2 replies; 36+ messages in thread From: Markus Mottl @ 2001-03-22 13:01 UTC (permalink / raw) To: Hendrik Tews; +Cc: OCAML Hendrik Tews schrieb am Thursday, den 22. March 2001: > I would like to vote for solutions that work for the common case > when writing large programs, even if they are hacks, considered > from a theoretical point of view. I am not so fond of sacrificing theoretical beauty: it usually seems to be the case that there are working solutions that are also elegant - it's only a matter of thinking about them long enough. You might speed up development a bit by allowing hacks if you cannot immediately find a sound solution, but IMHO it is hardly ever a good idea in the long run. > I think that in this case the theoretical cleaness is overrated. In general? Probably not. If there is a problem with expressiveness or else, it seems to be better to first try harder to find a solution with the existing system before crying for a hacky extension. And if this doesn't work, let's try to find a more expressive theory rather than abandoning theory completely. > Cross module recursion of functions is soo useful, that it > should be made to work --- even if the solution seems stupid with > respect to the example above. Nearly everytime I had thought "now I need recursive modules", I found other, even elegant ways to do it. If we really want them, please let's don't put aside theory but take existing clean solutions (e.g. see Claudio Russo's thesis). > [duplications in signatures and structures] > > Is the practical value of this kludge enough to forget that it's a > kludge? > > Sure. The solution to put the whole signature into a separate .ml-file requires hardly any work and solves this problem neatly. Why introduce a kludge if there are reasonable ways to do it? > No, at least I cannot. Do you have examples where the current system is just too awkward to use? > Also here I would suggest to have a > solution that works for the common case. What about changing > include, such that including a signature into a structure > includes all types and all exceptions? But you can do this (and I do it regularly) by putting the signature stuff into a separate module (or .ml-file): then you can "include" things in your structures to your hearts delight (thanks to the new way of using "include" with structures). Regards, Markus Mottl -- Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 13:01 ` Markus Mottl @ 2001-03-22 16:56 ` Brian Rogoff 2001-03-22 17:13 ` Daniel de Rauglaudre ` (2 more replies) 2001-03-27 8:21 ` Hendrik Tews 1 sibling, 3 replies; 36+ messages in thread From: Brian Rogoff @ 2001-03-22 16:56 UTC (permalink / raw) To: Markus Mottl; +Cc: Hendrik Tews, OCAML On Thu, 22 Mar 2001, Markus Mottl wrote: > Hendrik Tews schrieb am Thursday, den 22. March 2001: > > I would like to vote for solutions that work for the common case > > when writing large programs, even if they are hacks, considered > > from a theoretical point of view. > > I am not so fond of sacrificing theoretical beauty: it usually seems > to be the case that there are working solutions that are also elegant - > it's only a matter of thinking about them long enough. You might speed > up development a bit by allowing hacks if you cannot immediately find > a sound solution, but IMHO it is hardly ever a good idea in the long run. I agree with this general principle, and to be honest, I haven't found in my own programming a compelling case where module spanning mutually recursive function definitions were an issue. Is it possible to produce a reasonably sized example, Hendrik (or Chris)? I'm annoyed by the inability to have a mutually recursive *type* definition and functor instantiation, and that problem can be solved with recursive modules (Claudio Russo says it works in a development version of Mosml), but I haven't had this problem with functions yet. As an aside, Claudio mentioned that it would be easy to extend OCaml to support this feature: are there any plans to do so? If not, maybe I'll push for it when the Consortium is set up. > > Cross module recursion of functions is soo useful, that it > > should be made to work --- even if the solution seems stupid with > > respect to the example above. I agree that the workaround is a tiny bit ugly, but I'm not convinced that the problem is so great that it justifies any kind of new kludge. Convince me! My mind is open (or include'ed :) > Nearly everytime I had thought "now I need recursive modules", I found > other, even elegant ways to do it. How about the case I mention above? I think that there are a few cases where some extensions are necessary, however... > If we really want them, please let's don't put aside theory but take > existing clean solutions (e.g. see Claudio Russo's thesis). Yes. Let's have the extensions be clean, well founded ones. Even some people in industry realize that this is the right way to go. :-) I've snipped the module inclusion stuff because I think that while the need for a workaround is unfortunate, I think that there are bigger fish to fry. -- Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 16:56 ` Brian Rogoff @ 2001-03-22 17:13 ` Daniel de Rauglaudre 2001-03-23 17:30 ` Fergus Henderson 2001-03-27 22:11 ` John Max Skaller 2 siblings, 0 replies; 36+ messages in thread From: Daniel de Rauglaudre @ 2001-03-22 17:13 UTC (permalink / raw) To: caml-list Hi everybody, My usual hack for mutually recursive functions in different modules: File foo.ml: let g_ref = ref (fun _ -> failwith "Bar.g not yet defined") let g x = !g_ref x let f ... = .... g ... File bar.ml: let g .... = .... Foo.f ... Foo.g_ref := g By extending the language using Camlp4, by the constructions "forward" and "define_forward" doing the right thing, you could have: File foo.ml: forward g let f ... = .... g ... File bar.ml: let g .... = .... Foo.f ... define_forward g -- Daniel de RAUGLAUDRE daniel.de_rauglaudre@inria.fr http://cristal.inria.fr/~ddr/ ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 16:56 ` Brian Rogoff 2001-03-22 17:13 ` Daniel de Rauglaudre @ 2001-03-23 17:30 ` Fergus Henderson 2001-03-23 18:04 ` Brian Rogoff 2001-03-27 22:11 ` John Max Skaller 2 siblings, 1 reply; 36+ messages in thread From: Fergus Henderson @ 2001-03-23 17:30 UTC (permalink / raw) To: Brian Rogoff; +Cc: Markus Mottl, Hendrik Tews, OCAML On 22-Mar-2001, Brian Rogoff <bpr@best.com> wrote: > > I haven't found in > my own programming a compelling case where module spanning mutually > recursive function definitions were an issue. Is it possible to produce a > reasonably sized example, Hendrik (or Chris)? In the Mercury compiler, we have made significant use of module spanning mutually recursive procedures. For example, the code generator is split among several modules, roughly for each language construct (e.g. ite_gen handles code generation for if-then-elses, switch_gen handles code generation for switches, etc.), and since if-then-elses can contain switches (and vice versa), the procedures in these modules are mutually recursive. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp. ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-23 17:30 ` Fergus Henderson @ 2001-03-23 18:04 ` Brian Rogoff 2001-03-23 20:35 ` [Caml-list] Why People Aren't Using OCAML? (was Haskell) Mattias Waldau 2001-03-26 2:29 ` [Caml-list] recursive modules redux, & interface files Fergus Henderson 0 siblings, 2 replies; 36+ messages in thread From: Brian Rogoff @ 2001-03-23 18:04 UTC (permalink / raw) To: Fergus Henderson; +Cc: Markus Mottl, Hendrik Tews, OCAML On Sat, 24 Mar 2001, Fergus Henderson wrote: > On 22-Mar-2001, Brian Rogoff <bpr@best.com> wrote: > > I haven't found in > > my own programming a compelling case where module spanning mutually > > recursive function definitions were an issue. Is it possible to produce a > > reasonably sized example, Hendrik (or Chris)? > > In the Mercury compiler, we have made significant use of module spanning > mutually recursive procedures. For example, the code generator > is split among several modules, roughly for each language construct > (e.g. ite_gen handles code generation for if-then-elses, > switch_gen handles code generation for switches, etc.), > and since if-then-elses can contain switches (and vice versa), > the procedures in these modules are mutually recursive. Interesting. A similar example occurred in a discussion in comp.lang.ml between Matthias Blume and Greg Morrissett (concerning datatypes not functions) where MB argued as an SML/NJ maintainer that such recurrences were best placed in the same module and GM thought it best that they be split even though recursive. Clearly I lean towards MB's view on this though I take it that there are other schools of thought. What is your criteria for splitting the functions into different modules? -- Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* [Caml-list] Why People Aren't Using OCAML? (was Haskell) 2001-03-23 18:04 ` Brian Rogoff @ 2001-03-23 20:35 ` Mattias Waldau 2001-03-26 2:29 ` [Caml-list] recursive modules redux, & interface files Fergus Henderson 1 sibling, 0 replies; 36+ messages in thread From: Mattias Waldau @ 2001-03-23 20:35 UTC (permalink / raw) Cc: OCAML Something we should think about also for Ocaml http://www.jelovic.com/articles/why_people_arent_using_haskell.htm "What can be done about this? First and foremost the Haskell community must make a standard distribution of Haskell that contains enough libraries to be useful. That should include a regular expression library, an Internet protocol library, a library for dealing with standard internet data and encoding, a crypto library, a multimedia library and a GUI library. Next, the Haskell community must step out of its research circles and start publicizing Haskell to the practicing programmers. Write articles in DDJ and similar publications. Publish real-world programs written in Haskell." Most of this is also relevant for Ocaml, for example there are crypto libraries and XML-support (for example PXP, which require wlex, which is a hazzle). I stumbled over Ocaml, thanks to Mercury and ICFP-contest. /mattias ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-23 18:04 ` Brian Rogoff 2001-03-23 20:35 ` [Caml-list] Why People Aren't Using OCAML? (was Haskell) Mattias Waldau @ 2001-03-26 2:29 ` Fergus Henderson 1 sibling, 0 replies; 36+ messages in thread From: Fergus Henderson @ 2001-03-26 2:29 UTC (permalink / raw) To: Brian Rogoff; +Cc: OCAML On 23-Mar-2001, Brian Rogoff <bpr@best.com> wrote: > On Sat, 24 Mar 2001, Fergus Henderson wrote: > > > > In the Mercury compiler, we have made significant use of module spanning > > mutually recursive procedures. For example, the code generator > > is split among several modules, roughly for each language construct > > (e.g. ite_gen handles code generation for if-then-elses, > > switch_gen handles code generation for switches, etc.), > > and since if-then-elses can contain switches (and vice versa), > > the procedures in these modules are mutually recursive. > > Interesting. A similar example occurred in a discussion in comp.lang.ml > between Matthias Blume and Greg Morrissett (concerning datatypes not > functions) where MB argued as an SML/NJ maintainer that such recurrences > were best placed in the same module and GM thought it best that they be > split even though recursive. Clearly I lean towards MB's view on this > though I take it that there are other schools of thought. > > What is your criteria for splitting the functions into different modules? Our criteria are pretty informal: each module should consist of closely related code, preferably with a single purpose that can be summed up in a concise title, e.g. "code generation for if-then-elses". In this case, I think the code was originally in a single module, but was split into sub-modules when it became too large. Here's the line counts of the relevant modules: 768 call_gen.m 1296 code_gen.m 67 commit_gen.m 324 disj_gen.m 360 ite_gen.m 283 par_conj_gen.m 1254 pragma_c_gen.m 313 switch_gen.m 897 unify_gen.m 245 dense_switch.m 549 lookup_switch.m 246 string_switch.m 1100 tag_switch.m 584 middle_rec.m ---- 8286 Generally we prefer to make modules in the range of about 200-2000 lines of code each. If a module gets much larger than that, then it tends to get a bit unwieldy, and recompilation times start to become inconvenient, so we prefer to split up modules that get larger than that. 8000 lines is definitely way too big. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp. ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 16:56 ` Brian Rogoff 2001-03-22 17:13 ` Daniel de Rauglaudre 2001-03-23 17:30 ` Fergus Henderson @ 2001-03-27 22:11 ` John Max Skaller 2001-03-28 4:30 ` Brian Rogoff 2 siblings, 1 reply; 36+ messages in thread From: John Max Skaller @ 2001-03-27 22:11 UTC (permalink / raw) To: Brian Rogoff; +Cc: Markus Mottl, Hendrik Tews, OCAML Brian Rogoff wrote: > I agree with this general principle, and to be honest, I haven't found in > my own programming a compelling case where module spanning mutually > recursive function definitions were an issue. Is it possible to produce a > reasonably sized example, Hendrik (or Chris)? I have such an example. In the Vyper interpreter, there is a very large module which handles execution of ASTs, which contains almost all the interpretive code. It was not possible to break this module into further pieces because of the mutual recursion. [I actually _did_ do this, then undid it, because of the excessive number of extra arguments that had to be passed to make it work] Vyper is an extension of Python, which does things like: 1. The expression x + y is addition of numbers if x and y are numbers, otherwise, if x or y are objects of class type, method calls. 2. The expression eval(string) evaluates string in the current context which require mutual recursion across widely separates levels of otherwise fairly logical layers. I used indirection for most of these recursions (via a class object), but the lower level core execution was best handled by putting all the routines in one module. -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-27 22:11 ` John Max Skaller @ 2001-03-28 4:30 ` Brian Rogoff 2001-04-05 17:07 ` John Max Skaller 0 siblings, 1 reply; 36+ messages in thread From: Brian Rogoff @ 2001-03-28 4:30 UTC (permalink / raw) To: John Max Skaller; +Cc: caml-list On Wed, 28 Mar 2001, John Max Skaller wrote: > Brian Rogoff wrote: > > I agree with this general principle, and to be honest, I haven't found in > > my own programming a compelling case where module spanning mutually > > recursive function definitions were an issue. Is it possible to produce a > > reasonably sized example, Hendrik (or Chris)? > > I have such an example. In the Vyper interpreter, there is a > very large module which handles execution of ASTs, which contains > almost all the interpretive code. It was not possible to break this > module into further pieces because of the mutual recursion. This seems simialr to Fergus Henderson's example in the Mercury compiler. I thought his rationale was convincing (the file just got too big) and I assume he and you considered various refactorings to keep from splitting the module and decided against them. So even though there's practically no better example of functions that belong in the same module as mutually recursive ones, pragmatics suggests that you split them. None of the compiler like programs I've worked on have become that big yet. > [I actually _did_ do this, then undid it, because of the excessive > number of extra arguments that had to be passed to make it work] Yes, that can be a problem with the trick/hack of passing extra arguments. Did you consider the trick Daniel showed using function references which get initialized in the right order during the calls? I don't like introducing references unnecessarily but it might be useful until there is a cleaner solution. -- Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-28 4:30 ` Brian Rogoff @ 2001-04-05 17:07 ` John Max Skaller 0 siblings, 0 replies; 36+ messages in thread From: John Max Skaller @ 2001-04-05 17:07 UTC (permalink / raw) To: Brian Rogoff; +Cc: caml-list Brian Rogoff wrote: > Did you consider the trick Daniel showed using function references which > get initialized in the right order during the calls? Yes, but it's also just too messy. Many of the workarounds are probably OK for a few uses, but they don't really scale. With a 'fat' module, we get the simplest, cleanest, code, even if the module is rather large: interfaces are only useful if they help reduce complexity. The most scalable solution I found was to use classes to 'clump' related functions together, allowing a set of functions to be passed as a single argument (a class object). This also allowed some state to be put in the object instead of using a functional closure. -- John (Max) Skaller, mailto:skaller@maxtal.com.au 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] recursive modules redux, & interface files 2001-03-22 13:01 ` Markus Mottl 2001-03-22 16:56 ` Brian Rogoff @ 2001-03-27 8:21 ` Hendrik Tews 1 sibling, 0 replies; 36+ messages in thread From: Hendrik Tews @ 2001-03-27 8:21 UTC (permalink / raw) To: OCAML Hi, Markus Mottl writes: From: Markus Mottl <mottl@miss.wu-wien.ac.at> Date: Thu, 22 Mar 2001 14:01:57 +0100 Subject: Re: [Caml-list] recursive modules redux, & interface files Hendrik Tews schrieb am Thursday, den 22. March 2001: > I would like to vote for solutions that work for the common case > when writing large programs, even if they are hacks, considered > from a theoretical point of view. I am not so fond of sacrificing theoretical beauty: it usually seems to be the case that there are working solutions that are also elegant - it's only a matter of thinking about them long enough. You might speed up development a bit by allowing hacks if you cannot immediately find a sound solution, but IMHO it is hardly ever a good idea in the long run. [As an aside: In principle I do not agree that usually there exist elegant solutions. This would imply that for most problems there are elegant solutions, whereas the attribute elegant can only apply to a small subset of all solutions (unless everything is elegant). ] But for the main problem of mutual recursion: I would also appreciate a theoretically nice solution. But ocaml and its predecessors have been around now for long time, so it seems that it is not that easy to find a good solution for mutal recursion between modules. So instead of waiting another three years I would prefer a solution now, even if it is intermediate and not so clean. If there is a problem with expressiveness or else, it seems to be better to first try harder to find a solution with the existing system before crying for a hacky extension. And if this doesn't work, let's try to find a more expressive theory rather than abandoning theory completely. I agree, don't let's abandoning theory. But let's make a few compromises, where a good solution is not available in the near future. Nearly everytime I had thought "now I need recursive modules", I found other, even elegant ways to do it. I know, with some effort you can put every system in a linear structure and avoid module spanning recursion. But I do not want to restructure the whole project, only because I need some recursive functions. The more important point is that in a project with several people the overall complexity of the system structure must stay below a certain limit. If you create a system structure that is above this limit, then the project will fail. > [duplications in signatures and structures] The solution to put the whole signature into a separate .ml-file requires hardly any work and solves this problem neatly. Why introduce a kludge if there are reasonable ways to do it? I have the same argument here. Keeping three files instead of two is more complex. As a programmer you have to pay for this complexity and it doesn't buy you anything. The result is that people do not write interfaces because they do not like the additional effort it requires. Bye, Hendrik ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* [Caml-list] parser combinators 2001-03-21 18:41 ` Xavier Leroy 2001-03-22 0:23 ` Patrick M Doane 2001-03-22 12:02 ` Hendrik Tews @ 2001-03-30 10:27 ` Kevin Backhouse 2001-04-08 18:28 ` Daniel de Rauglaudre 2 siblings, 1 reply; 36+ messages in thread From: Kevin Backhouse @ 2001-03-30 10:27 UTC (permalink / raw) To: caml-list Is there a parser combinator library for OCaml? I would like to write a parser for Java and I gather that Java's grammar is LL(1). That might mean that parser combinators are better suited than yacc. thanks, Kevin Backhouse ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Caml-list] parser combinators 2001-03-30 10:27 ` [Caml-list] parser combinators Kevin Backhouse @ 2001-04-08 18:28 ` Daniel de Rauglaudre 0 siblings, 0 replies; 36+ messages in thread From: Daniel de Rauglaudre @ 2001-04-08 18:28 UTC (permalink / raw) To: caml-list Hello, On Fri, Mar 30, 2001 at 11:27:55AM +0100, Kevin Backhouse wrote: > Is there a parser combinator library for OCaml? I would like to write a > parser for Java and I gather that Java's grammar is LL(1). That might mean > that parser combinators are better suited than yacc. No, there is not, but you may consider using Camlp4 and its grammars. -- Daniel de RAUGLAUDRE daniel.de_rauglaudre@inria.fr http://cristal.inria.fr/~ddr/ ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2001-04-08 18:28 UTC | newest] Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-03-18 23:05 [Caml-list] recursive modules redux, & interface files Chris Hecker 2001-03-19 0:01 ` Brian Rogoff 2001-03-19 11:04 ` John Max Skaller 2001-03-19 11:41 ` Chris Hecker 2001-03-20 17:43 ` John Max Skaller 2001-03-21 4:03 ` Chris Hecker 2001-03-21 5:10 ` Patrick M Doane 2001-03-21 9:27 ` Chris Hecker 2001-03-21 18:20 ` John Max Skaller 2001-03-22 0:03 ` Patrick M Doane 2001-03-22 0:22 ` Brian Rogoff 2001-03-22 10:26 ` [Caml-list] duplication implementation/interface Judicael Courant 2001-03-22 11:16 ` [Caml-list] about typedefs... (was: duplication implementation/interface) Olivier Andrieu 2001-03-22 17:14 ` [Caml-list] duplication implementation/interface Brian Rogoff 2001-03-22 9:11 ` [Caml-list] recursive modules redux, & interface files Francois Pottier 2001-03-21 23:24 ` John Prevost 2001-03-22 0:00 ` Patrick M Doane 2001-03-21 18:18 ` John Max Skaller 2001-03-21 18:19 ` John Max Skaller 2001-03-22 11:40 ` Markus Mottl 2001-03-21 18:41 ` Xavier Leroy 2001-03-22 0:23 ` Patrick M Doane 2001-03-22 12:02 ` Hendrik Tews 2001-03-22 13:01 ` Markus Mottl 2001-03-22 16:56 ` Brian Rogoff 2001-03-22 17:13 ` Daniel de Rauglaudre 2001-03-23 17:30 ` Fergus Henderson 2001-03-23 18:04 ` Brian Rogoff 2001-03-23 20:35 ` [Caml-list] Why People Aren't Using OCAML? (was Haskell) Mattias Waldau 2001-03-26 2:29 ` [Caml-list] recursive modules redux, & interface files Fergus Henderson 2001-03-27 22:11 ` John Max Skaller 2001-03-28 4:30 ` Brian Rogoff 2001-04-05 17:07 ` John Max Skaller 2001-03-27 8:21 ` Hendrik Tews 2001-03-30 10:27 ` [Caml-list] parser combinators Kevin Backhouse 2001-04-08 18:28 ` Daniel de Rauglaudre
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox