Hello
Here is the latest Caml Weekly News, for the week of 12 to 19 October, 2004.
Archive: http://caml.inria.fr/archives/200410/msg00117.html
Johann Spies asked and Samuel Mimram answered:> Are there any libraries available for ssl-connections using ocaml? I have made small & quick bindings to ssl to be able to use ssl encryption with unix sockets. I am willing to improve it, just tell me if you need some (or much) more functions. The library is named ocaml-ssl and you can find it here : http://savonet.sf.net/Jason Hickey also answered:
We use openssl in MetaPRL and have implemented an appropriate OCaml API. I have extracted the SSL-specific files and placed them in http://www.cs.caltech.edu/~jyh/ssl . This can get you started, but it may be a bit more than what you want--it also includes buffered IO and a printf function. You can strip the buffered IO code if you want just a plain socket interface.
Archive: http://caml.inria.fr/archives/200410/msg00122.html
Tony Edgin asked:What is the reasoning behind Ocaml not allowing the public methods of a class to be hidden? Some times its nice for a class to have "global" public methods (Java's public methods) as well as public methods local to its module (Java's unprefixed methods). This allows for progressive encapsulation, where more distance modules no very little about a class, while the more local modules know more about the class. Inheritance could be used to approximate this, but sometimes subtyping makes more sense. I apologize for my lack of clarity. For those who couldn't understand my question, here's an example. module RandomVariables = struct class type rv_type = object method instance : float method scale_by : float -> rv_type method add : rv_type -> rv_type end class gaussian _stdev _mean = object method stdev = _stdev method mean = _mean method instance = (* elided *) (** Returns a draw from the corresponding distribution. *) method scale_by a = new gaussian ((abs_float a)*._stdev) (a*._mean) method add (other : guassian) = let sigma = sqrt (_stdev**2. +. other#stdev**2.) and mu = _mean +. other#mean in new gaussian sigma mu end (* Truncated *) end (* Bad code which I would like to use *) class gaussian_rv = (RandomVariables.gaussian float -> float -> RandomVariables.rv_type) ;;Jacques Garrigue answered:
> What is the reasoning behind Ocaml not allowing the public methods > of a class to be hidden? This is just a type soundness problem: as an ocaml object type only describes the interface of an object, you have no way to make sure that an object had originally a specific method (with the right type) once you have hidden it. Of course we could add some kind of declaration like method hidden m : type and allow a subclass to convert a public method into such an "hidden" one, but I'm quite sure this is not what you are asking for? (Note that such an addition would be rather heavy, as "hidden" method must appear in object types too, i.e. < hidden m : type; ... >) > Some times its nice for a class to have "global" public methods > (Java's public methods) as well as public methods local to its > module (Java's unprefixed methods). This allows for progressive > encapsulation, where more distance modules no very little about a > class, while the more local modules know more about the class. > Inheritance could be used to approximate this, but sometimes > subtyping makes more sense. This problem has been thought of :-) Look at the user's manual, section 3.17, for how to define "friend" methods, i.e. methods accessible only from code in the same module. Note that since ocaml modules are hierarchical, this actually allows you more precision than Java's packages. http://wwwfun.kurims.kyoto-u.ac.jp/soft/ocaml/htmlman/manual005.html#ss:friendsJohn Prevost added:
To expand a bit on what Jacques said, there are a lot of places in O'Caml where there are very very elegant ways to do things that a background in more traditional OO languages might not make you think of. Here's a version of your original code that highlights just a couple of those things: module RandomVariables = (struct (* First thought: What if we make a generic random_variable class that could work for types other than float? The most generic version can only describe its type and the method that returns an instance of the RV. Here we see a class type with a type variable, describing a method instance that returns a value of that type. There's no real reason to define this class type, except to provide a shorthand--when we say "x random_variable", we mean a random variable that returns values of type x. *) class type ['a] random_variable = object method instance : 'a end (* Of course, the rv_type class that you originally described had slightly more functionality. Specifically, a scale_by method and an add method. The first thing to note here is the type 's, which is the "self type" for the object. An object that is a float_random_variable has a method scale_by that takes a float and returns a new object with the same type as the original object. Likewise, add on an object of type t takes a second object of the same type, and returns a new object of the type those objects share. This also shows us that if we want to add arbitrary random variables together (not just random variables of the same type), we're going to have to do things differently some day. The "inherit [float] random_variable" is shorthand for including that class type in this class type, specialized for the given type "float". Since O'Caml uses structural subtyping, it's not necessary to inherit just to say that this is a subtype. But it's easier than duplicating the definition. *) class type float_random_variable = object ('s) inherit [float] random_variable method scale_by : float -> 's method add : 's -> 's end (* This is the trick shown in the O'Caml manual for "friends". We define a new type gaussian_repr, which will carry the "secret value" for our gaussian random variables. We can't use the module type to hide the existence of a method for getting the internal representation--but we *can* prevent anyone outside this module from making use of the value once they get it. See below in the module's signature. *) type gaussian_repr = { g_stdev : float; g_mean : float } (* The class is refactored slightly. Note the use of {< ... >} instead of "new gaussian ...". This ensures that the new object is of the same type as the original object. If you ever want to inherit from gaussian to re-use code, this means that the inheriting class will work correctly, instead of returning gaussians it will return new instances of itself. Notice that we had to make a field repr to hold the internal state, instead of using the constructor's closure. Without the "val repr", we can't use {< ... >} to copy the object and change the intenral state of the new copy. The "method value" is another part of the friends trick. Notice how we use it in add to get the repr of the other gaussian. We could instead have hidden the return types of the original "stdev" and "mean" methods in your version--but I chose to change it to this so that it doesn't look too odd. Remember we can't get rid of the methods, so users of the API would wonder "why can't I get the stdev and mean out of the gaussian?!?" *) class gaussian stdev mean = object (_ : 's) val repr = { g_stdev = stdev; g_mean = mean } method value = repr method instance = (*fake*) repr.g_mean method scale_by a = {< repr = { g_stdev = (abs_float a) *. stdev; g_mean = a *. mean } >} method add (other : 's) = let repr' = other#value in let sigma = sqrt (repr.g_stdev ** 2.0 +. repr'.g_stdev ** 2.0) in let mu = repr.g_mean +. repr'.g_mean in {< repr = { g_stdev = sigma; g_mean = mu } >} end end : sig (* Okay. Signature time. The class types are identical. *) class type ['a] random_variable = object method instance : 'a end class type float_random_variable = object ('s) inherit [float] random_variable method scale_by : float -> 's method add : 's -> 's end (* And here's where we hide the type of the representation. We don't give a type equation after "type gaussian_repr", so the type becomes opaque outside of this module. *) type gaussian_repr (* And now the definition of the gaussian class's type. Here I just inherit all of the methods defined in the float_random_variable class type, and then add a new method "value", which returns type "gaussian_repr". The name might be even better "gaussian_internal_state" or whatever, to show why the type definition is hidden from outside. *) class gaussian : float -> float -> object inherit float_random_variable method value : gaussian_repr end end) And then we can proceed to use the above, which does compile cleanly. Now, something to note: Even though we inherit float_random_variable in the type for class gaussian, gaussian is not, and never will be, a subtype of float_random_variable. The trouble is that we have a binary method here. Because add has type 's -> 's, we can never discard any internal state access methods. Why not? Think about what happens if you put a variety of float_random_variables in a list. Now you take the first two items in the list and try to use #add on them. Say the first is a gaussian RV and the second is a log random variable. The definition of the method add can't deal with this--it will try to hand the log random variable's state to the internals of the gaussian RV, which has no idea how to deal with it. HOWEVER, if we throw away the binary methods, we can in fact put a collection of "float random_variable" objects in a list. Here's some output from an ocaml session: # let a = new RandomVariables.gaussian 0.0 1.0;; val a : RandomVariables.gaussian = <obj> # let b = (a :> RandomVariables.float_random_variable);; This expression cannot be coerced to type { lots of error stuff, which boils down to "can't get rid of that method" } # let c = (a :> float RandomVariables.random_variable);; val c : float RandomVariables.random_variable = <obj> As you can see, casting to float_random_variable didn't work, but casting to float random_variable worked just fine. The system is preventing us from doing something unsound: using a bunch of mixed float_random_variables together in a way that wouldn't work (because we can't add them together). But when we mix them in a way that will work (we'll only make instances of them), all is well. The kinds of things that are problemmatic in this system are far different from the kinds of things that are tricky in traditional OO systems. But with some experience, you can see how the system is amazingly powerful. I suggest reading not only the section of the manual on friends, but all of Chapter 3 (Objects in Caml) and Chapter 5 (Advanced examples with classes and modules). And feel free to ask about suggestions about how to structure your system. From the looks of your code, I have some ideas about where you might be going, and about designs that might work better in a few places. If you do ask, make sure to describe your problem in terms of what you want to do, rather than how you want to do it. (i.e. "I want to be able to add arbitrary random variables together", not "I want to be able to get run-time type information on my random variables so that I can find the code to add them together in the right way.")
Archive: http://caml.inria.fr/archives/200410/msg00155.html
Yoann Padioleau announced:the goal is to allow the programmer to write in his program for instance: let _ = print_string (generic_print [[1;3];[2;9;8];[3;4]] "int list list") in ... let _ = print_string (generic_print [1;3;2;9;8;3;4] "int list") in let v = ... (* big computation, big data structure *) let _ = print_string (generic_print v "(int * float * color) assoc") in ... and to get on stdout: [[1; 3]; [2; 9; 8]; [3; 4]] [1; 3; 2; 9; 8; 3; 4] [(1, 2.02, Red); (2, 4.02, Yellow)]; the type of generic_print is 'a -> string -> string code: http://www.irisa.fr/prive/padiolea/hacks/generic_print.ml the principle is that the toplevel of O'Caml know how to print value, so by "reusing" the toplevel, our program can too. It is slow, ugly, not robust, but it can be helpful. any suggestion or critics are welcome.Nicolas Cannasse asked and Yoann Padioleau answered:
> I was thinking doing the same some times ago, but without relying on > toplevel (which stucks you to bytecode). I am not stuck to bytecode. the main program can be compiled to native code. I can also do: ocamlopt unix.cmxa str.cmxa generic_print.ml -o test_generic ocamlmktop -o calc.top unix.cma str.cma generic_print.ml > The idea was to be able to load CMI at runtime, and extract type > informations from it in order to correctly print and match types (this is > already what's doing ODLL with functions). It's quite a work and I didn't > finished it. CMI contains *exact* types informations which are not present > at runtime, but not structured in a convenient way for printing or matching > since they're directly dumped from the compiler type representation. But > once done, this would include some dynamism that ocaml lacks when > interacting with outter world (serialization for example). I've coded too in a more cleaner way a trick to achieve the same kind of result (a generic print) by relying on camlp4. I auto-generate string_of_.... function for each type (by doing an induction over the AST of the type definition via camlp4). It was cleaner. But i tend to prefer this uglier version :)
Archive: http://caml.inria.fr/archives/200410/msg00178.html
Matthias Blume asked:Dear fellow ML-ers, as far as I can tell, the last ML workshop was held with ICFP'98. Therefore, I think it is high time for a restart of this valuable tradition. I am planning to submit a proposal for an ML workshop to Patricia Johann, the ICFP'05 Workshop Chair. But for this I need your help! Information on the proposal process can be found on this web page: http://www.brics.dk/~danvy/icfp05/call-for-workshops.html As you can see, the deadline for proposals is coming up very soon (November 1st), so we need to act quickly. In order of importance, I would like each of you to take a few minutes and respond to the following questions: 1. Would you be interested in attending a new ML workshop, to be held in conjuction with ICFP'05 in Tallin, Estonia? 2. Would you be willing to help organizing the event? (I am willing to do my part, but I could use a few experienced "old hands".) 3. Would you be willing to serve on the program committee (should you be asked). 4. Among researchers and students you know and who were not reached by this communication, how many do you think would be interested in attending? (We need a reasonable estimate on the total numer of attendees.) 5. If anyone could help me out with details on publicity and potentially published proceedings, I'd be very grateful. 6. If you notice that I missed someone who should have received this request but didn't, please forward it! Thanks! Given the short time frame, please don't delay your reply! Many thanks in advance, and let's hope we all meet in Tallin (and not just for ICFP)! Best regards, Matthias Blume blume@tti-c.org ------------------------ Draft statement of goals, shamelessly stolen from the '98 workshop (If you have suggestions for changes and improvements, please speak up!): The ML family of programming languages, whose dialects include Classic ML, Standard ML, Caml, and Objective Caml, has inspired a tremendous amount of language research, ranging from type inference to module systems to operational semantics to implementation. In large part ML typifies "HOT" (Higher-Order, Typed) language design and implementation. Draft CfP (again, for the most part shamelessly stolen; request for suggestions -- see above): We seek papers relevant to all ML-related topics including (but not limited to): * applications * extensions: objects, classes, concurrency, etc. * two-level language designs (Meta-ML, MetaOCaml, etc.) * type systems: inference, modules, specification, error reporting, etc. * implementation: compilers, interpreters, partial evaluators, garbage collectors, etc. * environments: libraries, tools, editors, debuggers, etc. * semantics Submitted papers should describe new ideas, experimental results, or informed positions regarding proposals for next-generation ML languages. In order to encourage lively discussion, submitted papers may describe work in progress.
The OMake team is proud to announce a new release of the OMake Build System - OMake 0.9.3. OMake is a build system, similar to GNU make, but with many additional features: o Support for large projects spanning several directories or directory hierarchies. o Comes with a default configuration file providing support for OCaml, C and LaTeX projects, or a mixture thereof. Often, a configuration file is as simple as a single line OCamlProgram(prog, foo bar baz) which states that the program "prog" is built from the files foo.ml, bar.ml, and baz.ml. o Fast, reliable, automated dependency analysis using MD5 digests. o Portability: omake provides a uniform interface on Win32 and on Unix systems including Linux and Mac OS X. o Builtin functions that provide the most common features of programs like grep, sed, and awk. These are especially useful on Win32. o Full native support for rules that build several things at once (such as ocamlopt building .cmx and .o). o Active filesystem monitoring, where the build automatically restarts whenever you modify a source file. This can be very useful during the edit/compile cycle. o A companion command interpreter, osh, that can be used interactively. The home site for OMake is http://omake.metaprl.org/ The changes in 0.9.3 include: - OMake now supports ocamlfind in its default configuration file (thanks to Bardur Arantsson for the initial patch). - OMake should now also work with OCaml 3.07 (in addition to 3.08). - A large number of bug fixes, including: - OMake should now compile correctly under Cygwin (thanks to Peter Jolly who provided the patch), - "double-colon" rules (that allow specifying multiple rules for the same target) should now work correctly, - kqueue-based file system monitoring (Mac OS X, FreeBSD) should now work correctly - array definitions should now work better. - Added a work around for the command line length limitation of lib.exe on Windows - Filesystem monitoring functionality now provides a choice whether to continue monitoring once the project is built successfully. OMake 0.9.3 is still an alpha release. While we have made an effort to ensure that it is bug-free, it is possible some functions may not behave as you would expect. Please report any comments and/or bugs to the mailing list omake@metaprl.org and/or at http://metaprl.org/bugzilla OMake is distributed under the terms of the GNU General Public License. OMake configuration files are distributed under the terms of an MIT-like license. OMake sources, as well as a number of Linux and Windows binaries are available from the OMake home page at http://omake.metaprl.org/
> I am still looking into Ocaml, but if I start to use it I am very > interested in using wxWidgets. I was thinking it would be good idea to > start an open source project on sourceforge (wxcaml.sf.net). > > How much of wxWidgets does your binding support? > > Have you though of using SWIG? Thank you for your interest to wxCaml. Before making it as an open source project, I think more revision is necessary because it's only starting point of ocaml binding to wxWindows. The state of the wxCaml is that there are lots of binding to wxWindow functions (widgets). "wc *.idl" shows that it has about 5700 lines (including some commented lines), and "wc wxcaml.ml" shows it has about 9000 lines. It means that it has many interfaces to wxWindow functions, almost to all basic widgets. You can find which widgets has binding or not by checking the "wxcaml.ml" file. As you know, lablgtk team makes very good modules and classes for ocaml binding of another widget library. I think the wxCaml project should follow the same direction as lablgtk Before following wxhaskell method, I tested "SWIG" but it didn't give me good impression. I remember it produced dull interfaces. Right now, I don't have enough time to proceed with wxCaml project, so I welcome anyone who wants to continue this project.
Here is a quick trick to help you read this CWN if you are viewing it using vim (version 6 or greater).
:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1
zM
If you know of a better way, please let me know.
If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.
If you also wish to receive it every week by mail, you may subscribe online.