Previous week Up Next week

Hello

Here is the latest Caml Weekly News, for the week of 31 January to 07 February, 2006.

  1. Type-safe interface to Postgres's SQL
  2. OCaml & .NET
  3. async networking

Type-safe interface to Postgres's SQL

Archive: http://thread.gmane.org/gmane.comp.lang.caml.general/32091

Richard Jones announced:
Last year I wrote about my idea for a type safe interface to
PostgreSQL here:

http://caml.inria.fr/pub/ml-archives/caml-list/2005/07/857083d0d55ca642e4452ab82abd02cc.en.html
(See also Alex Baretta's criticism in the same thread).

Well, I actually implemented this after a lot of pain:

http://merjis.com/tmp/pgocaml-0.1.tar.gz

A typical type-safe program is attached to the end of this message.

There are a number of unanticipated problems with the implementation:

(1) Error reporting is a bit confusing.  Actually I think this is an
issue for any non-trivial camlp4 extension to the language.  You get a
message which doesn't relate to code which you actually wrote, but
instead to the code expanded from the macro.

(2) PostgreSQL doesn't track NULL types properly so we have to do a
bit of non-trivial guesswork to try to find out if a database field
could contain a NULL or not (and therefore whether to map its type to
'a or 'a option).  For parameters this isn't possible at all, so all
parameter variables must have an option type.  For result fields, it
is usually possible to tell if the result corresponds to a known
column in the database, which is the case in ninety percent of
queries.

(3) You need to have access to the real database at compile time, as
discussed in my original message.  This is because we prepare the
statements on the database engine and then ask the database engine to
tell us the types of the parameters / results, and use this to
generate code which makes the magic of type inference work on the
OCaml side.  Of course we don't _execute_ the statements at compile
time - which would have horrible side-effects.  Except that in some
cases we need to execute the statement at compile time.  The
particular case is when the statement is "CREATE TEMPORARY TABLE",
because subsequent code needs to actually have the temporary table
there in order to check later statements which access this table.  So
I've added a special case to cope with "CREATE TEMPORARY TABLE", which
might be regarded as something of a hack.  You would probably never
need to use this hack in Real Code, but the nature of test scripts
like the one attached is that they do create temporary tables.

BTW, I don't think any of this is necessarily "better" or "worse" than
the existing PG interfaces out there -- just different.

Rich.

----------------------------------------------------------------------
(* Example program using typesafe calls to PostgreSQL.
 * $Id: test.ml,v 1.3 2006/01/31 13:22:36 rich Exp $
 *)

open Printf

let () =
  let dbh = PGOCaml.connect () in

  PGSQL_EXECUTE_ON_COMPILE(dbh) "create temporary table employees (
     id serial not null primary key,
     name text not null,
     salary int4 not null,
     email text
  )";

  let insert name salary =
    PGSQL(dbh) "insert into employees (name, salary)
                values ($name, $salary)"
  in
  insert (Some "Ann") (Some 10_000_l);
  insert (Some "Bob") (Some 45_000_l);
  insert (Some "Jim") (Some 20_000_l);
  insert (Some "Mary") (Some 30_000_l);

  let rows = PGSQL(dbh) "select id, name, salary, email from employees" in
  List.iter (
    fun (id, name, salary, email) ->
      let email = match email with Some email -> email | None -> "-" in
      printf "%ld %S %ld %S\n" id name salary email
  ) rows;

  PGOCaml.close dbh
		
Chris Quinn said and Brian Rogoff answered:
> A few years ago I implemented a type safe interface to db2 (odbc
> compliant).
> My approach was to extend the caml compiler with a Type.typeof : 'a ->
> typeinfo function
> which marshalled the internal type info into a string.
> This is then used at runtime to compare with the database's notion of
> what a query produces
> (the check is performed only once during the execution life of the
> program, thereby minimising cost)
> So any mismatch with the db schema is caught (as long as that bit of the
> code is actually run!)

Sounds like GCaml (http://www.y1.is.s.u-tokyo.ac.jp/~furuse/gcaml) would have
allowed you to express this directly. The better typed marshalling has been
on my wishlist for a while
		

OCaml & .NET

Archive: http://thread.gmane.org/gmane.comp.lang.caml.general/32112

William W Smith asked:
Has anyone tried porting OCaml to managed code as a
Microsoft .NET family language?  

A related question is whether there any library sets
to access the windows API or MFC directly?
		
John Skaller answered:
Microsoft Research has, its called F#.

http://research.microsoft.com/projects/ilx/fsharp.aspx
		
Brian Hurt gave another link:
Take a look at F#:
http://blogs.msdn.com/dsyme/

It's not precisely Ocaml.NET, but it's pretty dang close.
		
Jean-Marc Eber suggested:
You should also have a look at

http://www.pps.jussieu.fr/~montela/ocamil/

even if I don't know precisely the current state of this project.
		
Harry Chomsky answered the second question:
> A related question is whether there any library sets
> to access the windows API or MFC directly?

A couple of years ago I took a stab at wrapping large parts of the Win32 API 
into an OCaml library.  You can download the library here:

http://www.speakeasy.org/~hchomsky/ocaml-win32.html
		

async networking

Archive: http://thread.gmane.org/gmane.comp.lang.caml.general/32123

Rick Richardson asked and Gerd Stolpmann answered:
> I found a post on the list from about 4 years ago where a gentleman
> expressed interest in developing an async net library in/for ocaml
> modelled after medusa. 
> 
> I have the exact same aspirations, actually, I'd rather just *use* a
> quality async library than build one. Can anyone suggest such a library?

Maybe you interested in my equeue library for multiplexing I/O. There is
now a lot of code using equeue (HTTP client, FTP client, RPC
implementation), so I think it is very stable.

http://www.ocaml-programming.de/programming/equeue.html
		
Bardur Arantsson suggested:
If you want ease of use and all-round stability I can also recommend
Gerd's Equeue. However, if you want very high-performance networking
you'd be better off with something closer to the metal, i.e. something
like a libevent wrapper combined with a memory-mapped ring buffer to
avoid unnecessary copying and minimize the costs associated with string
allocation and GC. I have developed a highly efficient ring buffer 
library (ocaml-rbuffer) which can be downloaded at

    http://www.imada.sdu.dk/~bardur/personal/45-programs/index.html
		
John Skaller answered:
> However, if you want very high-performance networking
> you'd be better off with something closer to the metal, i.e. something
> like a libevent wrapper 

Argg no. Libevent isn't a library, it doesn't control invert.
It is a monolithic framework. Therefore it is not very useful because
your code will no longer be composable. In particular,
there is no way to compose two such frameworks, for example
you cannot use it with an event driven GUI framework.

To quote the manpage:

"In order to process events, an application needs to call
event_dispatch(). This function only returns on error, and should
replace the event core of the application program."

Just try telling a GUI that *also* demands you use ITS 
event loop that!

The only proper way to use libevent would be to spawn the
dispatch loop inside a pthread, and use the hook functions
to communicate with your program via channels. It isn't
immediately clear this would work (libevent's single page
of documentation doesn't explain if it works when spawned
inside a pthread).
		
Pierre Etchemaïté suggested:
I came across a wrapper for the libevent library...
(No personnal experience with it, sorry)

	http://www.xs4all.nl/~mmzeeman/ocaml/
		

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}$'?'<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