Core has landed

We are proud to announce the first public release of core, Jane Street’s own alternative to OCaml’s standard library. We use this library as the base for our own development, and we hope people on the outside will find some use for it as well. People should be warned that

core is still in flux: there are interfaces that we have plans to change, so if you’re not willing to come along for the ride, you shouldn’t use it. Also, be warned that conformance with the OCaml standard library is not a goal, and we have already deviated from it in a number of ways. It’s also worth noting that we have only used and tested this library on x86 and x86-64 on Linux, and we make no claims about other platforms.

» Continue Reading.

using with type on a variant type

Here’s a type-checking problem I ran into today. I had a module with a variant type matching a signature that exposed the variant type.

  1. module type S = sig
  2. type t = A | B
  3. end
  4.  
  5. module M : S = struct
  6. type t = A | B
  7. end

I wanted to extend the module with some new functions, and match a new signature that extended the original signature. Easy, right?

» Continue Reading.

OCaml Annoyance #23: type declarations are implicitly recursive

Unlike let declarations, type declarations in OCaml are automatically recursive. This seems harmless at first, but it actually causes more trouble than it’s worth. To see why, let’s look at an example. Here’s a simple signature that uses nested modules and that adopts the reasonable convention of using t for the primary type of a module.

  1. module Thing : sig
  2. type t
  3.  
  4. module Collection : sig
  5. type t
  6. end
  7.  
  8. val create : string -> t
  9. val collect : t list -> Collection.t
  10. end

Unfortunately, implementing this is made more painful by the fact that type declarations are recursive by default. If you do the obvious thing:

» Continue Reading.

The ML sweet spot

I just got back from visiting Northeastern and Harvard where I yet again flogged a version of my POPL talk. Olin Shivers was my host at Northeastern and Greg Morrisett at Harvard. It was a bit of a rushed visit, but a lot of fun nonetheless.

Both Greg and Olin are very interested in making the next big jump in programming languages, and they both think that that next step will require better ways of reasoning statically about programs. I think they’re dead-on in terms of what the right direction to go is, but I think they’ve got their work cut out for them. It will be hard to beat ML because ML sits in a kind of sweet spot; make it a little bit better in one aspect, and you give something up in another. I can think of two ways in which this is true. The first has to do with the expressiveness of the type system. If you make the type system much more expressive, you generally need to give up a lot on the type-inference side and in the quality and comprehensibility of error messages. You can actually see this at work in OCaml. Some of the more advanced features, like polymorphic variants and objects, do indeed suffer from more obscure error messages and worse type inference than the rest of the language. I think polymorphic variants in particular are worth the trouble, but it just underlines the fact that adding to the Hindley-Milner type system is tricky. And compared to some of the things Olin and Greg and others in the PL community are thinking about, OCaml’s extensions to HM are pretty tame.

» Continue Reading.

Bind without tears

One of the annoyances of using monads in OCaml is that the syntax is awkward. You can see why if you look at a simple example. Assume that you’re using the usual option monad. If we define >>= to be the bind operator, you might end up with a piece of code that looks like this:

  1. let f x_opt y_opt z_opt =
  2. x_opt >>= (fun x ->
  3. y_opt >>= (fun y ->
  4. z_opt >>= (fun z ->
  5. return (x + y + z))))

This is awful for two reasons: the indentation is absurdly deep, and secondly, and there are too many closing parens at the end. One solution to this is

» Continue Reading.

Variable-argument functions

Here’s another puzzle:

Is it possible in OCaml to define a variable-argument function? For example, can one define a function f and values a and z such that the following assertions hold:

  1.  
  2. assert (f z = 0);
  3. assert (f a z = 1);
  4. assert (f a a z = 2);
  5. assert (f a a a z = 3);
  6. ...

Once you’ve got that, how about generalizing it to a variable-argument sum, i.e. define

» Continue Reading.

Typing RPCs

At Jane Street, we end up writing lots of messaging protocols, and many of these protocols end up being simple RPC-style protocols, i.e., protocols with a client and a server, where communication is done in a simple query/response style.

I’ve always found the writing of these protocols rather unsatisfying, because I could never find a clean way of writing down the types. In the following, I’d like to describe some nice tricks I’ve learned recently for specifying these protocols more cleanly.

A Simple Example

I’ll start with a concrete example: a set of RPCs for accessing a remote filesystem. Here are the signatures for a set of functions that we want to make available via RPC.

» Continue Reading.

Using let module for matching

In OCaml, referring to constructors defined in other modules can be somewhat awkward. Suppose we have a module like the following.

  1. module Example = struct
  2. type t = Foo | Bar | Baz
  3. end

To write a function that pattern matches on values of type Example.t we could directly refer to the variants as follows.

» Continue Reading.

Extracting an exception from a module

The Unix module defines the Unix_error exception constructor.

  1. module Unix : sig
  2. exception Unix_error of error * string * string
  3. ...
  4. end

Suppose you want to create your own My_unix module that defines some Unix utility functions and exports the same Unix_error. How would you do it? You can’t redeclare

» Continue Reading.

A universal type?

Is it possible in OCaml to implement a universal type, into which any other type can be embedded? More concretely, is possible to implement the following signature?

  1. module type Univ = sig
  2. type t
  3. val embed: unit -> ('a -> t) * (t -> 'a option)
  4. end

The idea is that t is the universal type and that embed () returns a pair (inj, prj), which inject to and project from the universal type. Projection is partial (returns an option) because injection is not surjective.

» Continue Reading.

4