OCaml Weekly News

Previous Week Up Next Week

Hello

Here is the latest OCaml Weekly News, for the week of July 03 to 10, 2018.

For people receiving this by email, I'm trying to send it as a multipart/alternative email with the text and html version. Please let me know if there is an issue.

Table of Contents


Sightings of OCaml around the Web

Yotam Barnoy announced

Here's a must-read article on the dev team's Plans for OCaml 4.08 by @lpw25 . If you're a long-time user, you'll really enjoy this.

Also, I'll just mention that OCamlverse has had quite a few updates recently. If you haven't checked it out yet, please do – everyone can request and receive automatic contribution rights, so if there's something you want to fix up/contribute to, you're welcome to do so.


Looking for OCaml developers for a Tezos based Decentralised Betting Exchange!

Suraj Tirupati announced

My team and I are working on a decentralised betting exchange called BettingWin - https://www.bettingwin.online

We want to create a platform through which users can place bets in a decentralised environment; bettors bet, market makers create markets and reporters report events. It's still in development and we are looking to work with some new developers.

We are currently looking to expand our team and bring on some developers to complete paid tasks or become a permanent member of the team depending on our compatibility :) We are really interested in working with smart, insightful developers who are familiar with OCaml and have experience with programming smart contracts. Also, any developers with an interest in Tezos are very welcome as that is the blockchain we are using.

We can arrange Skype calls to discuss things in detail. Please contact me at suraj@bettingwin.online


Dune 1.0.0 is coming soon, what about jbuilder projects?

Jérémie Dimino announced

The 1.0.0 release of dune is planned for next week. It will be the first release of jbuilder as dune, so what to expect for existing jbuilder projects?

The good news is that dune is fully backward compatible with jbuilder. The dune package in opam will install both dune and jbuilder binaries and both will be usable on existing jbuilder projects.

We do want to stop supporting jbuilder projects eventually, so the plan is to continue to support the jbuilder binary and jbuild files for another year. 6 months from now dune will start displaying warnings when using the jbuilder binary or jbuild files. A more detailied [migration plan][mp] is available in the manual. In particular it contains a precise list of things to do to migrate a jbuilder project to a dune project.

We hope that the new features in Dune 1.0.0 and subsequent releases will be enough of an incentive for users to eagerly switch to Dune :)

Important changes in Dune

This section is not an exhaustive list of changes, but it describes the important changes to expect when switching from jbuilder to dune.

  • Versioning and configuration files

    A big part of the work in Dune 1.0.0 was getting the versioning story right. With jbuilder it was hard for us to make the language evolve without breaking the build of existing projects. Dune can handle that gracefully and in the future it will be much easier to introduce breaking changes.

    The versioning of all dune files in a project is controlled via a single dune-project file at the root of the project. This file contains the version of the dune language and extensions used in the project.

    While this file is required in order to ensure compatibility with future versions of Dune, it is not required to write one by hand every time you start a new project or want to do a quick experiment. Dune will create and edit this file for you as needed, so simply start by creating a dune file (the new jbuild files) and dune will take care of the rest.

    Note that the syntax inside dune, dune-project, … files is slightly different from the one inside jbuild files. In particular the language requires fewer parentheses and the syntax of variables changed from ${...} to %{...} to avoid issues with shell commands. This is detailed in the [migration plan][mp] as well.

  • Build profiles and default settings

    Up to now jbuilder supported a --dev option in order to enable stricter flags. There have been several changes regarding this. First of all you are now able to define as many build profiles as you want: dev, release, perf, … These can be selected either via the --profile command line option or via the dune-workspace file. You are also able to define what the default compilation flags mean for each profile via an [env stanza][env].

    Another important change is that the default build profile for the dune binary is dev rather than release. We found that most of the time developpers want the development mode by default. Please remember to add "-p" name to all invocations of dune in opam files! This is now even more important than before in order to ensure the release profile is selected for opam builds.

  • Default target

    Dune allows to configure what happens when you run dune build without any specific targets. This is done via the introduction of a [default alias][defal].

  • More parellelism by default

    If you had (jobs N) in you ~/.config/dune/config file, you can remove it. Dune now automatically sets the number of jobs that can be run in parallel to the number of processing units available. The previous default was 4. For opam files, you should remember to add "-j" jobs in order to let opam decide.

Future of Dune

Now that we have a good versioning story and with the new testing tools that are emerging, I'm hoping that at some point we will be able to declare that the master of Dune is stable. At this point opam releases will just become a monthly or even weekly formality. This should make the experience nicer for both developers and users of Dune.

[mp]: https://dune.readthedocs.io/en/latest/migration.html
[env]: https://dune.readthedocs.io/en/latest/dune-files.html#env
[defal]: https://dune.readthedocs.io/en/latest/usage.html#default-alias

Jérémie Dimino then added

One thing I forgot to mention: if you have a ~/.config/dune/config file, you need to add the following line at the beginning of this file: (lang dune 1.0). This line is the one we use in every configuration file that is versionned and versioning the ~/.config/dune/config file seemed natural. The jbuilder binary doesn't require it for backward compatibility reasons, but the dune binary does.


New release of craml, a tool to test command line applications

Thomas Gazagnaire announced

I am happy to announce the first release of craml, a toool for testing command-line applications.

To install it:

opam install craml

The tool is already used by real-world OCaml v2 to test shell script examples and by merlin. Feedback is alway welcome, so feel free to open new issues on the tracker to discuss about new features.

Here is a copy of the README, with a more complete description of the project:

craml: a tool for testing command-line applications

CRAM is a is functional testing framework for command line applications. craml is freely inspired by the Python tool, which was itself based on Mercurial's unified test format.

craml is released as a single binary (called craml) and supports the following syntax:

  • Lines beginning with two spaces, a dollar sign, and a space are commands and will be run in the shell.
  • Multi-lines commands end by \ and continue with two spaces and a > sign on the next line:
$ <line1> \
> <line2> \
> <line3>
  • Lines beginning with two spaces are considered command output.
  • Command outputs can contains ellipsis: .... These will match any possible outputs (on zero, one or multiple lines).
  • Lines starting by <-- are command pre-conditions; they will determine the conditions where the command is run. Currently, only non-deterministic modes are supported as pre-conditions (see below).
  • Lines starting by --> are command post-conditions. Currently, only exit codes are supported as post-conditions (see below).
  • Anything else is a comment. It is not possible to put comments in the middle of an output as it is not clear what should be done to them when the output changes.

To run the tests described in a <file>, use craml <file>. This will run all the commands in sequence and will generated <file>.corrected if one of the output do not match the expected command outputs.

  • Non-deterministic Outputs

    craml supports non-deterministic outputs:

    <-- non-deterministic
      $ <command>
      <output>
    

    In that case, craml <file> will run the command but will not generate <file>.corrected if the new output differs from the one described in the file. Use craml --non-deterministic <file> to come back to the default behaviour.

  • Non-deterministic Commands

    craml supports non-deterministic outputs:

    <-- non-deterministic [skip]
      $ <command>
      <output>
    

    In that case, craml <file> will not run the command. Use craml --non-deterministic <file> to come back to the default behaviour.

  • Exit Codes

    craml tests exit codes:

      $ <command>
      <output>
    --> exit 10
    

    If <command> does not exit with code 10, then craml <file> will generate <file>.corrected with the right exit code. Note that @@ exit 0 will not be displayed.

Perry E. Metzger said and Daniel Bünzli replied

> Just a small request: I note that the README, which many users will never see on installing from opam,

Also note that an odig readme craml will do.


How to read/understand function signature with GADT?

Volodymyr Melnyk asked

For example, given the code:

let rec eval : type a . a term -> a = ...

How to read/understand this part: type a . a term -> a? What does the dot here mean? Why should we define type a in the function's signature?

octachron

There is two things going on simultaneously here. The first is that GADTs can only add equation to abstract types in a pattern matching. For instance, let's consider the toy example

type a = Tag_a
type b = Tag_b
type _ t =
  | A: a t
  | B: b t

then

let to_string = function
  | A -> "a"
  | B -> "b"

yields a type error

> Error: This pattern matches values of type b t
       but a pattern was expected which matches values of type a t
       Type b is not compatible with type a

because the type of the argument was inferred to a t in the first branch of the pattern matching.

The solution is to make the type phantom parameter of t a locally abstract type in to_string.

let to_string (type t) (x: t) = match x with
  | A -> "a"
  | B -> "b"

The notation (type t) introduces a local abstract type named t, since the type is abstract, it can be refined to different types in the branches of the pattern matching.

The second point is that recursive function involving GADTs often needs to be recursive polymorphic. For instance, with a toy langage,

type _ term  =
  | Bool : bool -> bool term
  | Int : int -> int term
  | If : bool term * 'a term * 'a term -> 'a term

an eval function would look like

let rec eval (type t) (x:t term): t = match x with
| Bool b -> b
| Int x -> x
| If (cond,then',else') -> if eval cond then eval then' else eval else'

but in the If branch eval is called with an argument of a different types, which result in a type error

> Error: This expression has type t term but an expression was expected of type
         bool term

on the first call with a different value for the term type parameter. The long-winded solution here is to add an explicit polymorphic annotation and then introduce locally abstract types

let rec eval: 't. 't term -> 't = fun (type t) (x: t term): t -> match x with
| Bool b -> b
| Int x -> x
| If (cond,then',else') -> if eval cond then eval then' else eval else'

Since this is a bit of a mouthful, there is shorter variant that directly combines explicit polymorphic annotation with locally abstract types:

let rec eval: type t. t term -> t = function
| Bool b -> b
| Int x -> x
| If (cond,then',else') -> if eval cond then eval then' else eval else'

Here type t. … ~ declares ~t as both a locally abstract types and makes it explicitly polymorphic.


Format module from the Standard Library

cloudyhug asked

Hello everyone. Does any of you know where I can find a decent tutorial for the OCaml Format module ? I cannot figure out how to use it, and the few things I have found are the documentation and the official tutorial, which are explicit but not clear at all. I have spent the last 30 minutes trying to understand it, in vain.

Gabriel Radanne replied

I would recommend reading this blog post: https://cedeela.fr/format-all-the-data-structures.html

For understanding boxes, see https://ocaml.org/learn/tutorials/format.html

Martin Jambon also replied

If that's an option for you, I'd suggest using easy-format. There's a complete example here with various ways to format the same thing.


First release of mastodon-archive-viewer (0.1)

Kate announced

Mastodon is a decentralized social network similar to Twitter.

One of its many features is to allow people to get their archive as a way to save their posts history in case one server is seized, crashed, or temporary down. It is also useful in case you want to delete an old account but still want to keep its archive.

Here I present you mastodon-archive-viewer which is a tool that takes a mastodon archive, previously exported, downloaded and extracted and gives you an offline web view of it.

If you want to give it a try, mastodon-archive-viewer is now available on opam, and comes with a filter system to view only parts of your archive.

opam install mastodon-archive-viewer
cd <archive-directory-previously-extracted>
mastodon-archive-viewer outbox.json > archive.html

For the moment this tool is in an early stage of development so don't hesitate to report bugs or feature requires on the issues tracker.

Happy tooting!

PS: if you are interested in using Mastodon, perhaps a legit choice of instance might be functional.cafe, for example :slight_smile:


Other OCaml News

From the ocamlcore planet blog

Here are links from many OCaml blogs aggregated at OCaml Planet.


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.