Previous week Up Next week

Hello

Here is the latest Caml Weekly News, for the week of 26 April to 03 May, 2005.

  1. Engineer position at Cristal@INRIA
  2. Type inference question
  3. Savonet releases liquidsoap 0.2.0
  4. New tutorial on Camlp4: "How to customize the syntax of OCaml, using Camlp4"
  5. Mini ray tracer
  6. Changes on equality between 3.06 and 3.08.3
  7. pftdbns 0.2.2
  8. Bantam: a lightweight file manager for X11

Engineer position at Cristal@INRIA

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/38663b36c2e7971eebe0dd989798f3cd.en.html

Michel Mauny announced:
Please forward this announce to whom might be interested.

INRIA-Rocquencourt (Cristal group) is seeking for an engineer whose
task will be to develop a specific version of the Caml language in
partnership with an an IT manufacturer. More information at
http://quincy.inria.fr/ing-en.html .
    

Type inference question

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/33ea2e8128a2d90f6a1514d180dc6271.en.html

Julien Verlaguet asked and Jean-Christophe Filliatre answered:
> I have the following function definition :
> 
> let myfun param=
>    let res=Marshal.from_channel stdin [] in
>      if res=param then
>        res
>      else res
> 
> I was expecting : myfun : 'a -> 'a
> 
> I got instead : myfun : 'a -> 'b
> 
> Is it normal ?

Yes.  "Marshal.from_channel stdin  []" has  type 'a  and this  type is
generalized  in the  let/in  construct, giving  res  the type  "forall
'a. 'a". In the test "res = param", the type of res is instanciated on
the type of param, but this does not affect the type of the result.

It would be better if  Marshal.from_channel would be given a type that
cannot  be generalized ('_a)  but I  don't think  that the  ocaml type
system can do this.

Anyway, it is  always a good idea to use a  type constraint when using
marshalling functions, as in

        let (x : tau) = Marshal.from_channel ...
    
Mark Shinwell then asked and Jacques Garrigue answered:
> > Yes.  "Marshal.from_channel stdin  []" has  type 'a  and this  type is
> > generalized  in the  let/in  construct, giving  res  the type  "forall
> > 'a. 'a". In the test "res = param", the type of res is instanciated on
> > the type of param, but this does not affect the type of the result.
> 
> I can understand this behaviour in a case such as the following:
> 
>         let f v =
>           let r = fun x -> x in
>             if r = v then r else r
> 
> where as you say the (non-trivial) type scheme assigned to r is
> instantiated multiple times, yielding ('a -> 'a) -> 'b -> 'b for f.
> 
> However, in the Marshal example above, we have
> 
>         Marshal.from_channel stdin []
> 
> in the first part of the "let".  In the SML terminology, this is not a
> "nonexpansive expression"[*] (unlike "fun x -> x").  Therefore, I would
> have thought that the appearance of such an expression here would
> prohibit generalisation (in order to prevent possible unsoundness in the
> presence of mutable state).  This is presumably not the case in OCaml:
> can someone explain why?
> 
> Mark
> 
> [*] http://www.smlnj.org//doc/Conversion/types.html

Because ocaml now uses an improvement of the so-called "value restriction".
Rather than refusing to generalize any variable in expansive
expressions, it generalizes covariant ones, as they cannot be
used in an unsound way.
(See "Relaxing the value restriction" at
 http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/papers/)

What we see here is a consequence of that for functions which
are known as typing holes: any function that returns a totally
unconstrained result (as input_value or Obj.magic) allows this result
to be generalized. Actually, for Obj.magic this is a good thing: you
sometimes want the result to be polymorphic (this is not a real
function anyway). For input_value this is subject for discussion, but
anyway this function is a glaring hole in the type system... maybe we
should have a way to explicitly require its result to be annotated
with a ground type!
    

Savonet releases liquidsoap 0.2.0

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/620595164517ee253e0c180d5eaaa0b7.en.html

David Baelde announced:
The Savonet project aims at building a complex web-radio system,
completely written in OCaml.

We are proud to finally release the first stable version of liquidsoap,
the heart of the Savonet system! Not only is it stable, it is also very
rich, as demonstrated by examples on our website. Unfortunately, we
can't make a public demonstration web-radio. Gentoo ebuilds are
available, and Debian packages should be released soon. Check on our
website:

http://savonet.sourceforge.net

Here's a list of the released packages, featuring newly released
sub-projects and many major bug fixes:

* liquidsoap-0.2.0
  Programmable and extensible audio stream generator,
  allows any kind of audio manipulation.

* ocaml-dtools-0.1.1
  Utilies for logging, configuration,
  and startup/shutdown services of your OCaml applications.

* ocaml-ftp-0.1.0
  FTP file access.

* ocaml-smbclient-0.1.0
  Bindings for libsmbclient, for Samba file access.

* ocaml-fetch-0.1.0
  Transparent remote/local file access.

* ocaml-mad-0.1.3
  Bindings for libmad, for encoding/decoding MP3.

* ocaml-mp3id3-0.2.0
  For reading Mp3Id3 tags.

* ocaml-vorbis-0.2.0
  Bindings for libvorbis+libogg, for encoding/decoding Ogg/Vorbis.

* ocaml-shout-0.2.0
  Bindings for shout2 library for streaming ogg/mp3 audio data.

* ocaml-ssl-0.2.0
  Bindings for libssl, provinding secure sockets.

Thanks to all that work, liquidsoap is a very powerful and flexible
audio streaming language, abstracting over format, protocol, stream
generation, manipulation and output. Allowing arbitrarily deep-nested
composition of streams and easy extensibility, it gives you more power
than you need for creating an original web-radio. But liquidsoap is
still very light and easy to use, in the Unix tradition of many simple
strong components working together.

The web-radio we're running accepts user requests, and then search in
a database for matching songs. The database feeder is not yet released,
but is available on CVS. Other unmaintained parts of the project are a
website and an OCaml IRC bot, making easy the user requests and playlist
querying. Instead we're currently using an unpublished Perl hack. All of
these components were expected to communicate using libsavonet, using
authentification, and directly exchanging caml values over network.

Hope our project interests a few of you,
and demonstrate that OCaml is a great real-life programming language.
    

New tutorial on Camlp4: "How to customize the syntax of OCaml, using Camlp4"

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/0cb1293570b0f1fd9d36e904eeee929e.en.html

Martin Jambon announced:
I am pleased to announce the availability of this new online resource:

  "How to customize the syntax of OCaml, using Camlp4"

URL: http://martin.jambon.free.fr/extend-ocaml-syntax.html
    

Mini ray tracer

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/d22b1761efb27d7b182cb9eabf245e1c.en.html

Jon Harrop announced:
I just knocked up a little ray tracer in OCaml to test its viability for the 
shootout:

  http://www.ffconsultancy.com/free/ray_tracer/

Here, it traces a 768^2 image of 66,430 spheres in 22.51s on a 1.2GHz 
Athlon-Thunderbird and in 7.24s on a 1.8GHz Athlon 64.

I've boiled it down to 94 LOC and posted it to the shootout mailing list.
    

Changes on equality between 3.06 and 3.08.3

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/677f99f4fc250f84c4b36c7594f137a9.en.html

Olivier Michel asked and Damien Doligez answered:
> I just noticed the following change in Ocaml between release 3.06 and 
> 3.08.3, as far
> as equality on records is concerned :
>
> # type toto = { b : int -> int; };;
> type toto = { b : int -> int; }
> # let a = { b = (fun x -> x) } ;;
> val a : toto = {b = <fun>}
> # a = a;;
> Exception: Invalid_argument "equal: functional value".
>
>
> Is this supposed to be a bug, or a feature ? Will future releases of 
> Ocaml follow
> the new way of handling equality between records or the old one ?

New feature.  Carefully thought out.  Well documented.  Ultimately 
caused by a strange wart of the IEEE floating-point standards.

You should use the "compare" function if you want the old behaviour.
    
Alex Baretta said:
Keep in mind that in 3.06 physical equality (==) implied structural 
equality (=). Now, (=) now longer checks for (==), so no functional 
value can be found to be structurally equal to any other functional 
value. The following line illustrates this point.

# (=) (=) (=);;
Exception: Invalid_argument "equal: functional value".

Actually, an interesting question related to this one is why the 
following line behaves as it does.

# (==) (==) (==);;
- : bool = false
    
Olivier Andrieu answered and Marcin Kowalczyk added:
> Probably because == is defined by an "external" in pervasives.ml,
> not a regular function definition. So here, when you use (==),
> you're building three closures.

Two. OCaml materializes function objects corresponding to external
functions each time they are used instead of once at the point of
their definition (presumably because it assumes that usually they are
not passed as first-class objects at all), but application of such
function doesn't need the function object but jumps straight to its
machine code.
    
Jon Harrop then said:
# let f = (==) in (==) f f;;
- : bool = true

Interesting. I don't like it, but it's interesting. :-)
    

pftdbns 0.2.2

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/04/29ca2e908ec620baea6f17300835ae5b.en.html

Oliver Bandel announced:
I have to announce a tool which is useful in sorting/listing/moving files.

It's name "pftdbns" is a short hand for "put files to directories (sorted) by name structure".

It takes filenames, maps each char of the filename into a char, representing
the charclass of it (a..z and A..Z -> "l" (letter), 0...9 -> "d" (digit" and so on).

Thsi yields to an easy way of sorting files by names, based upon file-naming
with certain filenaming-conventions.

So, for example  "hello.txt" and "ballo.txt" are part of the same name structure,
as well as "1001.txt" and "8251.txt" but also "8251.jpg" are of the same name
structure.

The default behaviour is to move files into directories. The names of the directories
are choosen from the string, which represents the name structure.

But since version 0.2.2 this defaulkt behaviour can be overriden, so that the
files will not be moved, but only the names (or names and the namestructure strings)
will be printed.

So, I hope you enjoy this program, and I think if you have to handle a lot
of files, this will be very helpful.

You can find the tool here:
        ftp://www.belug.org/new/user/ob/Programs/Tools/pftdbns/ 

There also is a README in this directory, so that you can read more details.

A description can also be found here:
   http://www.belug.org/~ob/ftp-area.html 

pftdbns uses the GPL-license.
    

Bantam: a lightweight file manager for X11

Archive: http://caml.inria.fr/pub/ml-archives/caml-list/2005/05/cca768b52b2c21cf6ba35ad3558bf17e.en.html

Matt Gushee announced:
[ ... written in OCaml, of course! ]

To make a long story short: I couldn't find a file manager that had just 
the right combination of features, so I created Bantam. It attempts to 
be a fast, light, unobtrusive productivity aid for power users of 
POSIX/X11 systems. Important features include:

  * An arbitrary number of directory views
  * Single-keystroke commands
  * Internal text file viewer
  * Configurable interface to external viewers and editors
  * A minimum of visual clutter (i.e. no icons, etc.)

Bantam 0.1 is now available in source and Linux binary packages. The 
binary should work on any system with Tcl/Tk 8.4 installed. If you have 
any trouble installing or running it, *please* let me know.

The Bantam home page is http://matt.gushee.net/software/bantam/ .
    

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 (version 6 or greater).

:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'&lt;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 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.


Alan Schmitt