Previous week   Up   Next week
Hello,

Here is the latest Caml Weekly News, week 01 to 08 July, 2003.

1) Information flow analysis: Flow Caml
2) Fresh Objective Caml
3) announcing IBAL release
4) guis and wxwindows
5) CDuce
6) Printf and format
7) private constructors

==============================================================================
1) Information flow analysis: Flow Caml
------------------------------------------------------------------------------
** Vincent Simonet announced:

I am delighted to announce the first public release of

        Flow Caml

a prototype implementation of an information flow analyzer for the
Caml language.


Flow Caml is an extension of the Objective Caml language with a type
system tracing information flow.  Its purpose is basically to allow
to write "real" programs and to automatically check that they obey
some confidentiality or integrity policy.  In Flow Caml, standard ML
types are annotated with security levels chosen in a user-definable
lattice.  Each annotation gives an approximation of the information
that the described expression may convey.  Because it has full type
inference, the system verifies, without requiring source code
annotations, that every information flow caused by the analyzed
program is legal with regard to the security policy specified by the
programmer.

Technically speaking, Flow Caml is also one of the first real-size
implementations of a programming language equipped with a type system
that features simultaneously subtyping, ML polymorphism and full type
inference.


The source distribution can be downloaded at the following address:

       http://cristal.inria.fr/~simonet/soft/flowcaml/

It should compile on every Unix box where the Objective Caml compiler
and GNU Make are installed (and also Windows+Cygwin).  A binary build
for Windows operating system is also available.

A manual, which includes a comprehensive tutorial introduction to the
system, is also available:

       http://cristal.inria.fr/~simonet/soft/flowcaml/

This document has been written to be understandable by everyone who
has some programming experience in Caml (or another ML dialect),
without any prior knowledge about information flow analysis or
subtyping.


This implementation has been carried out from my joint work about
information flow analysis with François Pottier.  Comments are very
welcome.

==============================================================================
2) Fresh Objective Caml
------------------------------------------------------------------------------
** Mark Shinwell announced:

FRESH OBJECTIVE CAML
http://www.freshml.org/foc/

On behalf of the FreshML research project at the University of Cambridge
Computer Laboratory, I am pleased to announce the availability of Fresh
Objective Caml.

What is it?

Fresh O'Caml is an extension of the Objective Caml language
http://caml.inria.fr/ocaml/ with facilities for correctly manipulating
object-language syntax involving alpha-convertible names and binding
operations.

The current implementation of Fresh O'Caml is still somewhat 
experimental: many known optimisations have yet to be implemented and
there are undoubtably other shortcomings, or even bugs in the current
release.  Please bear this in mind if you use it!

Where to get it?

The Fresh Objective Caml source is available at
http://www.freshml.org/foc/  It should compile on any system
on which O'Caml builds.  Please note that a native-code compiler is not
provided at this time. The website also contains user documentation and
examples, together with links to two recent research papers which  
are relevant to the language.  Further background information on the
novel features that Fresh O'Caml adds to O'Caml is at the FreshML
Project web page http://www.cl.cam.ac.uk/~amp12/freshml/

Where to complain?

Should you have problems with Fresh O'Caml, please see
http://www.freshml.org/bugs/ Please don't bother the Caml team with
bug reports about Fresh O'Caml, even if the problem appears not to be
related to the new features.

Where to get help?

There is a new mailing list for general discussion about Fresh  
O'Caml and FreshML.  Please visit
http://lists.freshml.org/mailman/listinfo/freshml/ if you would like
to join, or to browse list archives.

==============================================================================
3) announcing IBAL release
------------------------------------------------------------------------------
** Avi Pfeffer announced:

I am pleased to announce the initial release of IBAL, a general purpose
language for probabilistic reasoning.  IBAL is highly expressive, and
its inference algorithm generalizes many common frameworks as well as   
allowing many new ones.  It also provides parameter estimation and
decision making.  All this is packaged in a programming language that
provides libraries, automatic type checking, etc.

IBAL may be downloaded from http://www.eecs.harvard.edu/~avi/IBAL

==============================================================================
4) guis and wxwindows
------------------------------------------------------------------------------
** Gergely Kontra asked and Nicolas Cannasse answered:

> I want to know what cross-platform gui's are available for ocaml.
> I know about gtk, but that's not so stable on windows.

Actually under Windows there is the OCaml Win32 API which is pretty much
low-level for programming GUIs , so I wrote Osiris which is a simple
framework for using GUIs with OCaml. Right know Osiris is only working using
native Win32 components, but a port of Osiris under LablGTK is on the way.
As soon it's done, the community will have a cross-platform gui simple
toolkit available.  

An old version of Osiris is available at http://tech.motion-twin.com

** Richard Jones also answered:

> I want to know what cross-platform gui's are available for ocaml.
> I know about gtk, but that's not so stable on windows.

I've actually been playing with Gtk + OCaml + Windows and it works
quite well, and the look and feel is closer to native than I expected.
Other alternatives are labltk (based on Tk) or the native Win32 API
(version 0.02 however, so perhaps not very stable or reliable? - can
anyone comment?). There is no WxWindows port AFAIK, which is a shame.

> To be frank I want to use wxWindows with ocaml. Has anybody began to
> work on it? If not, and I want to start developing it, can anybody give
> me practical hints, etc where to start?
>
> I'm not experienced neither in ocaml (-dev) nor wxwindows

http://www.merjis.com/richj/computers/ocaml/tutorial/

I should add a section on available GUIs, since I'm researching this
at the moment.

==============================================================================
5) CDuce
------------------------------------------------------------------------------
** Alain Frisch announced:

I'm pleased to announce the first public release of CDuce, a new
strongly typed higher-order functional programming language for XML
documents with an efficient type-based runtime implementation.  The
distribution can be downloaded at:

   http://www.cduce.org/download.html

More information can be found at:

   http://www.cduce.org/

And you can directly try CDuce with a web browser using the online
prototype at:

   http://www.cduce.org/cgi-bin/cduce

CDuce is fast, functional, type-safe, and conforms to basic standards:
Unicode, XML, DTD, Namespaces are handled, partial support of XML 
Schema validation is in alpha testing (and undocumented) while queries
are being implemented.

The OCaml community could be interested in CDuce because:

- CDuce syntax is reminiscient of ML languages (but CDuce has a
  completely different type system, with subtyping and intersection,
  union, negation types, and also a different type-based
  semantics with overloaded functions and pattern matching on types);

- CDuce is written in OCaml;

- Our research plans include the development of a CDuce <-> OCaml
  interface, to allow extending CDuce with OCaml and
  using CDuce for the XML part of OCaml applications.



This is the first beta version. All your comments, suggestions, and
bug reports are welcome. Please send all of them to info@cduce.org

==============================================================================
6) Printf and format
------------------------------------------------------------------------------
** Sylvain Le Gall asked and Pierre Weis answered:

> Is there a way to transform string to ( 'a, out_channel, unit, unit)
> format. I need this function to use it with something like :
>
> Printf.printf (my_fun "X, Y") "coucou";;
>
> I look at the code and see a function scan_format, but it seems to be
> forbid to use it.

As once announced on this list, the new release of Objective Caml will
introduce a lot of novelty on the format type.

Besides new convertion specifiers that you could find in the Printf
and Scanf documentation (C, S, B, F, !, ...), there are now several
different new functionalities provided by the new compiler which are
relevant to your question:

0) converting arbitrary format string to a regular strings

1) converting CONSTANT strings to the corresponding constant format string

2) concatenating format strings (very often feature 0 and 1 are used
in conjonction just to implement format strings concatenation).

Those primitives are provided with respective names string_of_format,
format_of_string, and binary infix operator ( ^^ ). I think they are
useful and powerful: those new features should leverage the need for
using Obj.magic and type constraints inside programs that directly
manipulate format strings.

However, this introduction of new format strings primitives has
necessitated the addition of a new type variable to the format type
that now get 4 variables instead of 3: this extra variable is
mandatory to adequately type-check the kprintf function and to give an
appropriate type to the new format concatenation operator (appropriate
here just meaning correct, i.e. safe).

This is normally completely transparent to programs that just use
printf-like functions: the printf functions get a type using the new
format type constructor, its format string get also the extra type
variable in its typing, the type-checker hapilly handles the
application and you will not even notice the modification.

However, this new type variable indeed introduces a backward
incompatibility, if you ever used the format type constructor into
your programs, as part of the type constraints appearing either in the
interface files or directly into your programs (to force an expression
to get a format type).

In this case, the modification of your program is easy and as follows:

 Just duplicate the last variable of the format type constructor argument.

This systematic way to correct programs that mentioned the format type
constructor is a minor inconvenience for the sake of the useful
additions described above.

If the users on this list feel it too complex and way too boring to
modify their programs like that, we may try to implement various hacks
to leverage the burden. I should mention that, even if I'm not
enthusiastic at all to have been obliged to introduce such a backward
incompatibility into the compiler, I would be ashame to add such (not
so clean) hacks into it as well. In particular, because in this case,
the modification of programs is almost trivial.

Back to your problem: the features described here may your for some
``my_fun'' functions, but the general case is not properly covered by
them. What we need is a general function that reads a format from
within a string that is NOT a constant. This is a kind of dynamic
convertion reminiscent of int_of_string or float_of_string, that
checks that the string can be indeed considered as an integer of
floatting point number.

I propose (and have implemented for my own programming of a general
translation function) a new function [read_format], such that

[read_format pat s] returns the string [s] as a format string that has
the same type (hence the same ``printf meaning'') as [pat], the first
format string argument.

For instance,

read_format "The number %d is odd" "Le nombre %d est impair"

returns "Le nombre %d est impair" as a format string with the same
type as "The number %d is odd".

This function is more general that the one above since now in
[read_format pat s] the string [s] is not mandatorily an immediate
string constant: it can be obtained from an arbitrary computation, as
read from a file.

The Typechecking of read_format would be:

read_format :
 ('a, 'b, 'c, 'd) format -> string -> ('a, 'b, 'c, 'd) format

If considered useful, this function could be added, for instance as
part of a new internationalization module.

** Xavier Leroy also answered:

> Is there a way to transform string to ( 'a, out_channel, unit, unit)
> format. I need this function to use it with something like :
>
> Printf.printf (my_fun "X, Y") "coucou";;

No, not in a type-safe manner.  The type of a format string depends on
the "%" specifiers found in the string itself, and OCaml can't infer
or check types at run-time.

However, for the purpose of internationalization, the following
operation suffices: given a (compile-time constant) format and a
(dynamically computed) string, check that the string can be viewed as
a format with the same format type as the constant format, and return
the string as a format.

In OCaml 3.06, this can be done as follows:

  let re_fmt =
    Str.regexp "%[#0-9.*+ -]*[lnL]?[sScCdioxXunfeEgGFbBatn[]"

  let string_of_format (s : ('a, 'b, 'c) format) = (Obj.magic s : string)

  let extract_formats s =
    List.fold_right
      (fun part accu ->
        match part with Str.Text _ -> accu | Str.Delim d -> d :: accu)
      (Str.full_split re_fmt s) []

  let conv_format (src: ('a, 'b, 'c) format) (dst: string) =   
    if extract_formats (string_of_format src) = extract_formats dst
    then (Obj.magic dst : ('a, 'b, 'c) format)
    else failwith "conv_format"

Remark 1: yes, there's a lot of "Obj.magic" in this code, and yes,
this is a deadly sin, but in this particular instance it is all
type-safe nonetheless.

Remark 2: the matching of the two formats can be relaxed, e.g.
the code above will not allow the conversion of "%6d" into "%8x",
although both formats have the same type.  This is left as an exercise
for the reader.  But for internationalization purposes, I doubt
you need that additional flexibility.

Then, assuming you have a function "gettext : string -> string" to translate
strings according to the user-selected language, you can extend it to
formats as follows:

  let getformat f = conv_format f (gettext (string_of_format f))   

and use it with printf functions like this:

  printf (getformat "My name is %s and I'm %d years old") "Bob" 12   

> you read my mind. Indeed, the question concern an internationalization
> module ( let's call libgettext-ocaml ). It is basically a binding of
> gettext.

I hope the above is enough to get you off the ground.

==============================================================================
7) private constructors
------------------------------------------------------------------------------
** John Max Skaller asked and Pierre Weis answered:

> For immutable values, establishing an invariant at construction
> time is enough to ensure the invariant is preserved: therefore,
> it is enough to make construction abstract to ensure all values
> of the type satisfy the invariants.

Exactly.

> Just for interest, this is not the case for mutable objects,
> for example:
>
>       type rational = private { mutable x: float; mutable y: float };
>       ...
>       let mess_up_invariant (z:rational) = z.y <- 0.0
>
> Be interested to know the treatment of records with mutable fields.
> Are they permitted? Or are the mutators disallowed?

Records with mutable fields are permitted. Mutators explicitely exported
as functions are allowed, other mutations are forbidden.

I once wrote a lot of arithmetics and helped people writing core
arithmetics libraries for Caml. I always thought we had a major flaw
in the design of the library, due to type abstraction: we were
constantly oscillating between two conflicting attitudes; on the one 
hand, using abstract data types all over the place to preserve
invariants and on the other hand turning to concrete types, not to be
forced to code everything ourself within the module implementing the
ADT.

I think private types are also a good answer to the  
problem. Implementation of rational numbers would use a record with
mutable fields, and define a rational creation and a normalization
functions, preserving invariants:

type rat = {
  mutable numerator : int;
  mutable denominator : int;
};;

let rec mk_rat n d =
 if d = 0 then failwith "mk_rat: null denominator" else
 if d < 0 then mk_rat (- n) (- d) else
 { numerator = n; denominator = d};;

(* Left as an exercise *)
let gcd n m = 1;;

let normalize_rat r =
 let g = gcd r.numerator r.denominator in
 if g <> 1 then begin
   r.numerator <- r.numerator / g;
   r.denominator <- r.denominator / g
 end;;

Then interface of the module would abstract creation and mutation:

type rat = private {
  mutable numerator : int;
  mutable denominator : int;
};;

val mk_rat : int -> int -> rat;;

val normalize_rat : rat -> unit;;

This way, there is no need to define access to numerator and
denominator, or even to write printing functions: the user can write
them easily:

open Rat;;

let print_rat r =
 normalize_rat r;
 match r with
 | { numerator = n; denominator = d} -> Printf.printf "%d/%d" n d;;   

Also, any attempt to mutate a rational is now statically rejected by
the typechecker:

let r = mk_rat 1 2 in
r.numerator <- 4;

Cannot assign field numerator of private type Rat.rat.

Hence, in a sense, private types can also serve as a primitive way to
turn a mutable data type into an immutable one outside its defining
implementation, provided that no mutating functions are exported.

A small addition for the language, a big step for the programmer :)

==============================================================================
Using folding to read the cwn in vim 6+
------------------------------------------------------------------------------
Here is a quick trick to help you read this cwn if you are viewing it using
vim (at least version 6).

:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1
zM

If you know of a better way, please let me know.

==============================================================================
Old cwn
------------------------------------------------------------------------------

If you happen to miss a cwn, you can send me a message
(alan.schmitt@inria.fr) and I'll mail it to you, or go take a look at
the archive (http://pauillac.inria.fr/~aschmitt/cwn/). If you also wish
to receive it every week by mail, just tell me so.

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

Alan Schmitt