caml-list - the Caml user's mailing list
 help / color / Atom feed
From: Alan Schmitt <alan.schmitt@polytechnique.org>
To: "lwn" <lwn@lwn.net>, "cwn"  <cwn@lists.idyll.org>, caml-list@inria.fr
Subject: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News
Date: Tue, 14 Jan 2020 15:16:52 +0100
Message-ID: <87pnfmt963.fsf@polytechnique.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 24944 bytes --]

Hello

Here is the latest OCaml Weekly News, for the week of January 07 to 14,
2020.

Table of Contents
─────────────────

Calling a single function on every member of a GADT?
OCamlPro's opam cheat sheet, with a new theme!
OCaml 4.10.0, first beta
Data engineer positions at Elastic, US/Canada/Western Europe (proximate to NA timezones)
Release of naboris 0.1.0 a simple http server
esy@0.6.0 release
Old CWN


Calling a single function on every member of a GADT?
════════════════════════════════════════════════════

  Archive:
  <https://sympa.inria.fr/sympa/arc/caml-list/2020-01/msg00007.html>


Ivan Gotovchits asked
─────────────────────

  I'm basically trying to do the equivalent of this simple `fold'
  function:

  ┌────
  │ module Simple =
  │ struct
  │   type term =
  │      | Int of int
  │      | Add
  │      | App of term * term
  │ 
  │   let rec fold i f = function
  │     | Int _ as t -> f i t
  │     | Add -> f i Add
  │     | App (x, y) as t -> f (fold (fold i f x) f y) t
  │ end
  └────

  … but using a GADT:

  ┌────
  │ module Gadt =
  │ struct
  │   type _ term =
  │      | Int : int -> int term
  │      | Add : (int -> int -> int) term
  │      | App : ('b -> 'a) term * 'b term -> 'a term
  │ 
  │   let rec fold : type a. 'r -> ('r -> _ term -> 'r) -> 'r = fun i f -> function
  │     | Int _ as t -> f i t
  │     | Add -> f i Add
  │ (*
  │      ^ Error: This pattern matches values of type (int -> int -> int) term
  │ 	but a pattern was expected which matches values of type int term
  │ 	Type int -> int -> int is not compatible with type int
  │ *)
  │     | App (x, y) as t -> f (fold (fold i f x) f y) t
  │ end
  └────

  I've tried other variants of the syntax and got many encouragements
  but no green flag from the type-checker.  Why is the compiler
  expecting an int term in there? I though the whole point of the `type
  a. ...' syntax was to allow the matched type to vary from one pattern
  to the next?  Is there a way to do this?


Ivan Gotovchits replied
───────────────────────

  It is the limitation of the let-bound polymorphism. A parameter of a
  function is monomorphic in its body. The classical example doesn't
  even reference any GADT,

  ┌────
  │ let example f  = f "hello", f 42
  └────

  It won't compile even though we can provide a polymorphic function
  that can applied both to integers and to strings, e.g., `exampe (fun x
  -> x)' should be possible, but not, because of the let-bounded
  polymorphism. There are a few solutions available in OCaml, the
  simplest is to use records, e.g.,

  ┌────
  │ type app = {apply : 'a. 'a -> 'a}
  │ 
  │ let example {apply} = apply "hello", apply 42;;
  │ 
  │ val example : app -> string * int = <fun>
  └────

  Now we have `app' that is polymorphic.  In your case, I would define a
  visitor type, e.g.,

  ┌────
  │ type 'r visitor = {visit : 'a. 'a term -> 'r -> 'r}
  │ 
  │ let rec fold : type a. 'r -> 'r visitor -> a term -> 'r =
  │   fun i f t -> match t with
  │     | Int _ as t -> f.visit i t
  │     | Add as t -> f.visit i t
  │     | App (x,y) as t ->
  │ 	let i = fold i f x in
  │ 	let i = fold i f y in
  │ 	f.visit i t
  └────


Jacques Garrigue also replied
─────────────────────────────

  Actually, this is a rare case where using a polymorphic method may be
  handy too:

  ┌────
  │ let rec fold : type a r. r -> <v : 'b. r -> 'b term -> r> -> a term -> r =
  │      fun i f -> function
  │      | Int _ as t -> f#v i t
  │      | Add -> f#v i Add
  │      | App (x, y) as t -> f#v (fold (fold i f x) f y) t
  │ 
  │ let v =
  │    object method v : type a. _ -> a Gadt.term -> _ =
  │      fun x -> function
  │        | Int n -> x+n
  │        | Add -> x+1
  │        | App _ -> x+2
  │    end
  │ 
  │ let r = Gadt.fold 0 v (App (App (Add, Int 3), Int 5))
  └────

  The point being that to match on a Gadt you will anyway need to use
  the (type a) construct to allow refinement.


rixed asked and Ivan Gotovchits replied
───────────────────────────────────────

        So there is no lighter syntax to specify that `f' should
        accept any member of a GADT than the syntax to specify
        that `f' should accept any type at all?

  Only three methods of introducing rank-2 polymorphism are known to me:
  1. records
  2. objects
  3. first-class modules

  Jacques has demonstrated the solution with objects, which might be a
  little bit more lightweight, at least as you don't need to define a
  new data type beforehand. But the invocation is more verbose and
  requires an annotation from the caller side, which could be
  confusing. The third solution relies on first-class modules and is
  even more verbose, at least on the definition side. Just for the sake
  of completeness,

  ┌────
  │   module type Visitor = sig
  │     type t
  │     val term : t -> 'a term -> t
  │   end
  │ 
  │   let rec fold : type a r. r -> (module Visitor with type t = r) -> a term
  │ -> r =
  │     fun i ((module Visit) as f) t -> match t with
  │       | Int _ as t -> Visit.term i t
  │       | Add as t -> Visit.term i t
  │       | App (x,y) as t ->
  │ 	  let i = fold i f x in
  │ 	  let i = fold i f y in
  │ 	  Visit.term i t
  │ 
  │   let s = fold 0 (module struct
  │       type t = int
  │       let term x _ = x + 1
  │     end)
  └────

  And again, it is not about GADT. GADT act as a red herring here. As
  I've demonstrated earlier, using a simple pair will suffice to display
  the limitation of the prenex polymorphism. Even no ADT is required,
  just apply one term to another two and you will get them unified,
  e.g.,

  ┌────
  │ let f g x y : unit = g x; g y
  └────

  will have type

  ┌────
  │ val f : ('a -> unit) -> 'a -> 'a -> unit
  └────

  because 'a is quantified on the scope of `f' not `g', in other words,
  it has type (not an OCaml syntax)

  ┌────
  │ val f : forall 'a. ('a -> unit) -> 'a -> 'a -> unit
  └────

  while we would like to have a type

  ┌────
  │ val f : forall 'b, 'c. (forall 'a. 'a -> unit) -> 'b -> 'c -> unit
  └────

  OCaml doesn't allow us to define types like `('a. 'a -> 'a)' and the
  reason is not that it is hard to extend the parser it is…

        I wonder, is this just a limitation of the OCaml parser or
        is there some deep reason for these work-around (like is
        the case, from my understanding, for the value
        restriction)?

  Yep, good catch! It is because of the impurity. Indeed, Haskell has
  the Rank2Types extension that lets us write types like `(forall a. a
  -> ()) -> b -> c -> ()', with no extra syntactic burden (modulo having
  to provide the type annotation). But functions in Haskell are pure,
  therefore it is possible. To make the story short and obvious, let me
  do a simple demonstration of how things can go wrong in a language
  with side-effects.  Let's go back to the simple example of pairs and
  the identity function.  Consider the following nasty identity
  function,

  ┌────
  │ let bad_id () =
  │   let cache = ref None in
  │   fun x -> match cache.contents with
  │     | None -> cache := Some x; x
  │     | Some cache -> cache
  └────

  It has type `unit -> 'a -> 'a' therefore, if we would have the rank-1
  polymorphism enabled for functions, we could apply it to the function

  ┌────
  │ let map2 : fun ('a. 'a -> 'a) -> 'b -> 'c -> 'b * 'c = fun f (x,y) -> f x, f y
  └────

  as

  ┌────
  │ let x,y : string * int = map2 (bad_id ()) "hello", 42
  └────

  and will get a segmentation fault, as `y' will now have type int but
  hold a string.

  And here comes the syntax as a savior as it lets us specify functions
  that are guaranteed to be syntactic values. Indeed, all three
  solutions syntactically guarantee that the provided argument is a
  function, not a closure. Indeed, let's introduce the universal
  identity via a record,

  ┌────
  │ type id = { f : 'a. 'a -> 'a}
  └────

  and we can see that our `bad_id' is not accepted due to the value
  restriction, while good_id, defined as,

  ┌────
  │ let good_id x = x
  └────

  is perfectly fine, e.g.,

  ┌────
  │ let id1 = {f = good_id} (*accepted *)
  │ let id2 = {f = bad_id}   (* rejected *)
  └────

  moreover, even a fine, but not syntactic, identity is also rejected

  ┌────
  │ let fine_id () x = x
  │ let id3 = {f = fine_id ()} (* rejected *)
  └────

  with the message

  ┌────
  │ This field value has type 'b -> 'b which is less general than 'a. 'a -> 'a
  └────

  The same is true with modules,

  ┌────
  │ module type Id = sig
  │   val f : 'a -> 'a
  │ end
  │ module Id1 : Id = struct let f = good_id end   (* accepted *)
  │ module Id2 : Id = struct let f = bad_id () end (* rejected *)
  │ module Id3 : Id = struct let f = fine_id () end (* rejected *)
  └────

  and with objects (left as an exercise).

  To summarize, in order to enable rank2 polymorphism we need a special
  kind of values to bear universal functions, as we can't rely on
  ordinary functions, which could be constructed using partial
  application. OCaml already had objects and records, which serve as a
  fine media for universally quantified functions. Later first class
  modules were introduced, which could also be used for the same
  purpose. Probably, one could devise a special syntax (or rely on the
  new attributes and extensions syntax, e.g., `map2 [%rank2 : fun x ->
  x] ("hello",42)' but probably this will lead to an unnecessary
  bloating of the language and the implementation, especially since we
  already have three solutions with a more or less tolerable syntax (and
  are in the base language, not an extension).  Besides, if we will use
  the `[@@unboxed]' annotation, or visitor will have the same
  representation as a function, e.g.,

  ┌────
  │ type 'r visitor = {visit : 'a. 'r -> 'a term -> 'r} [@@unboxed]
  │ let count x _ = x + 1
  │ let counter = {visit=count}
  └────

  and

  ┌────
  │ # Core_kernel.phys_same count counter;;
  │ - : bool = true
  └────

  Concerning rank-n polymorphism, in OCaml is is achieved using
  functors.  Yes, they are a little bit syntactically heavy and force us
  to write signatures, but this is necessary anyway as rank-n is
  undecidable (non-inferrable). Finally, as a real-world example [1] of
  rank-2 polymorphism consider the universal WAVL tree that is a binary
  tree with each element having a different type (aka heterogeneous
  map). We use it in BAP as a backing store. You might find a few tricks
  there, especially using continuation-passing in the recursive cases.

  Cheers, Ivan

  [1]:
  <https://github.com/BinaryAnalysisPlatform/bap/blob/b40689e636607b977758af048b79d65684ce48c3/lib/knowledge/bap_knowledge.ml#L847-L1693>


Malcolm Matalka asked and Ivan Gotovchits replied
─────────────────────────────────────────────────

        Why is type checking creating a record different than type
        checking a function argument?

        If we had the syntax (or something like it):

        let map2 : ('a. 'a -> 'a) -> ('b * 'c) -> ('b * 'c)

        Why would the type checker not be able to see that

        map2 good_id ("hi", 42)

        is valid but

        map2 (fine_id ()) ("hi", 32)

        is not, using the same logic that is verifying creating
        the "id" record is not valid?

  I believe it is possible, as it is possible in Haskell (with
  RankNTypes and ScopedTypeVariables). The main (theoretical) difference
  is that in OCaml we need to check whether an expression is expansive
  and use a specialized generalization in case if it is (for the relaxed
  value restriction). It will, however, complicate the type inference
  engine a lot, but most importantly, changing the typing rule of
  functions will have a tremendous impact on the language. So this would
  be a very impractical solution.  Especially, since we don't have the
  mechanism of language extensions, enabling RankNTypes will make a lot
  of programs untypeable, as they will now require type annotations
  (recall that RankN is undecidable in general).  It could probably be
  implemented as a compiler command line parameter, like `-rectypes' but
  this will be still quite impractical since more often code like `fun f
  -> f 1, f true' is a programmer error, rather than a true request for
  universal polymorphism (the same as with rectypes, recursive types a
  more often an error rather than a deliberate attempt). Therefore,
  enabling RankN(^1) polymorphism will type too many programs (not that
  it is unsound, just many programs won't have sense) at the cost of
  even more obscure type errors. On the other hand, we have three
  syntactic constructs that let us express non-prenex polymorphism of
  the necessary rank(^2) without breaking anything else. So it looks
  like a good deal - we can have rankN polymorphism and decidable type
  checker at the same time. Just think of polymorphic records/methods as
  an embedded DSL for rankN polymorphism.

  `==========' Footnotes:

  1) An important point, that I forgot to notice, is that enabling
     scoped
  type variables, will inevitably enable rankN polymorphism, e.g., since
  now any type could be a polytype, then suppose we have type
  `'a. ('b.'b -> 'a) -> 'a' could be instantiated to 'a = 'd. ('c. ->
  'd) -> 'd, so that our type is now `'d. ('b. 'b -> ('c. 'c -> 'd) ->
  'd) -> ('c. 'c -> 'd) -> 'd' which is now rank3. Therefore, enabling
  arbitrary quantification in the arrow type will lead to rankN and
  immediately make undecidable most of the type checker.

  1) We can craft arbitrary rank using records with universally
     quantified
  type variables, e.g., here is an example of rank3 polymorphism:

  ┌────
  │ type 'a rank1 = {f1 : 's. 's -> 'a}
  │ type 'a rank2 = {f2 : 'r. 'r -> 'a rank1}
  └────

  Indeed, `f2' has type `'a.('r. 'r -> ('s. 's -> 'a)'


OCamlPro's opam cheat sheet, with a new theme!
══════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/rfc-ocamlpros-opam-cheat-sheet-with-a-new-theme/4689/3>


Thomas Blanc announced
──────────────────────

  The opam cheat-sheet is now published in its final form.

  You can get the [colored] and [black-and-white] versions from our
  website.

  Happy hacking!


[colored]
<http://www.ocamlpro.com/wp-content/uploads/2019/11/ocaml-opam.pdf>

[black-and-white]
<http://www.ocamlpro.com/wp-content/uploads/2020/01/ocaml-opam-bw.pdf>


OCaml 4.10.0, first beta
════════════════════════

  Archive: <https://discuss.ocaml.org/t/ocaml-4-10-0-first-beta/4989/1>


octachron announced
───────────────────

  The release of OCaml 4.10.0 is approaching. We have published a first
  beta version to help you adapt your software to the new features ahead
  of the release.

  During our preliminary tests for this new beta, we discovered that the
  recent work towards a multicore-ready OCaml runtime introduced
  compatibility issues within some opam packages, that were tweaking the
  runtime internals.  Most of those opam packages have been fixed, or
  will be soon.  Nevertheless, if you are affected by such compatibility
  issue, please speak up.

  The source code is available at these addresses:

  <https://github.com/ocaml/ocaml/archive/4.10.0+beta1.tar.gz>
  <https://caml.inria.fr/pub/distrib/ocaml-4.10/ocaml-4.10.0+beta1.tar.gz>

  The compiler can also be installed as an OPAM switch with one of the
  following commands.
  ┌────
  │ opam switch create ocaml-variants.4.10.0+beta1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
  └────
  or
  ┌────
  │ opam switch create ocaml-variants.4.10.0+beta1+<VARIANT> --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
  └────
  where you replace <VARIANT> with one of these:
  • afl
  • flambda
  • fp
  • fp+flambda

  We want to know about all bugs. Please report them here:

  <https://github.com/ocaml/ocaml/issues>

  Happy hacking.


Kate added
──────────

  For the people wanting to give OCaml 4.10.0beta1 a shot, here is an
  opam overlay which adds fixes to major packages for them to work with
  this beta: <https://github.com/kit-ty-kate/opam-alpha-repository>

  To use it, simple call:
  ┌────
  │ $ opam switch 4.10
  │ $ opam repository add alpha git://github.com/kit-ty-kate/opam-alpha-repository.git
  └────

  Obviously, this repository should not be used in production and
  probably contains a few bugs, but at least it allows everyone to have
  almost as many packages available as with OCaml 4.09. Only 60ish
  packages are still not available, but apart from the notable exception
  of `merlin' all the essential packages and dependencies are there.

  This work has been part of the release-readyness effort founded by the
  OCaml Software Foundation as announced here:
  <https://discuss.ocaml.org/t/ann-the-ocaml-software-foundation/4476/13>

  The rest of the effort is going to be put towards having `merlin'
  available for OCaml 4.10 and upstreaming all the fixes from
  opam-alpha-repository (most of them have PRs associated already). I'm
  hopeful for them be all upstreamed and available before the stable
  release of OCaml 4.10.


Data engineer positions at Elastic, US/Canada/Western Europe (proximate to NA timezones)
════════════════════════════════════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/job-data-engineer-positions-at-elastic-us-canada-western-europe-proximate-to-na-timezones/4991/1>


Hezekiah Carty announced
────────────────────────

  Our team here at [Elastic] has positions open for a few security data
  engineers (aka wranglers of data and all the systems involved).  We
  are a distributed company so you don't have to be close to an office
  to be considered.  Infosec industry experience is _not_ required,
  though of course welcome.  We're surrounded by experts in the field so
  you'll have lots of opportunities to learn as you go!

  The official postings are available here (both have the same text and
  only differ in title/seniority):
  • Security data engineer -
    <https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-data-engineer/2005140#/>
  • Senior security data engineer -
    <https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-senior-data-engineer/2005152#/>

  Language-wise, OCaml/Reason makes up most of the code you’ll be
  working on. Python makes up most of the rest, in particular taking
  advantage of the machine learning and natural language processing
  goodies that ecosystem provides. Most of the tools and service we
  develop are internally focused, supporting security research and
  improvements to security protections for our users. For those
  so-inclined, there are lots of opportunities to present at and attend
  conferences, present work in blog posts, contribute to open source
  software projects and otherwise engage the community.

  The positions are very similar to our [last hiring announcement],
  though we had a different name at that point!

  Please reach out to me if you have any questions. I’m available on the
  OCaml or Reason Discord servers or by email at
  hezekiah.carty@elastic.co.


[Elastic] <https://www.elastic.co/>

[last hiring announcement]
<https://discuss.ocaml.org/t/filled-posting-is-no-longer-open-threat-research-engineer-job-endgame-us/1937>


Release of naboris 0.1.0 a simple http server
═════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/release-of-naboris-0-1-0-a-simple-http-server/4994/1>


Shawn McGinty announced
───────────────────────

  <https://github.com/shawn-mcginty/naboris>

  I could use input on the API and the documentation.  Working on trying
  to improve both at the moment.

  The goal was to create a very simple library for building RESTful type
  of web servers.  Make it _very_ easy to manage handle request/response
  lifecycle and sessions.

  In my opinion this type of web server is a great entry point for new
  developers looking to explore the OCaml/Reason world.

  Recently I have fallen in love with OCaml and Reason, and as a mostly
  web centered developer I've found this area quite lacking.  I'm still
  new to the language and eco system so any guidance would be highly
  appreciated!


Yawar Amin replied
──────────────────

  Wow! It seems we had much the same idea–OCaml/Reason more accessible
  to web developers new to the ecosystem :-D I've been working on
  something very similar: <https://github.com/yawaramin/re-web/>


Ulrik Strid said
────────────────

  There is also opium <https://github.com/rgrinberg/opium>

  And morph <https://github.com/reason-native-web/morph> that has
  similar goals.

  It would be nice if we could either create a shared core that all
  could build from or collaborate on one.


esy@0.6.0 release
═════════════════

  Archive: <https://discuss.ocaml.org/t/ann-esy-0-6-0-release/5010/1>


Andrey Popp announced
─────────────────────

  We've just released a new version of esy. You can install it with npm:
  ┌────
  │ $ npm install -g esy@0.6.0
  └────

  [esy] is a package.json driven workflow for native development with
  Reason/OCaml (and even C/C++). It provides per-project build
  environments which are isolated from each other but share underlying
  build caches so creating new environments is cheap.

  While 0.6.0 is mainly about "quality-of-life" improvements it also got
  few new features including a basic support for garbage collection of
  unused build artifacts.

  For more info see a [blog post] by @prometheansacrifice which
  highlights important updates in 0.6.0.


[esy] <https://esy.sh>

[blog post] <https://esy.sh/blog/2020/01/12/0.6.0.html>


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]


[send me a message] <mailto:alan.schmitt@polytechnique.org>

[the archive] <http://alan.petitepomme.net/cwn/>

[RSS feed of the archives] <http://alan.petitepomme.net/cwn/cwn.rss>

[online] <http://lists.idyll.org/listinfo/caml-news-weekly/>

[Alan Schmitt] <http://alan.petitepomme.net/>


[-- Attachment #2: Type: text/html, Size: 53238 bytes --]

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2020-01-14 Tue 15:04 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OCaml Weekly News</title>
<meta name="generator" content="Org mode" />
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center;
             margin-bottom: .2em; }
  .subtitle { text-align: center;
              font-size: medium;
              font-weight: bold;
              margin-top:0; }
  .todo   { font-family: monospace; color: red; }
  .done   { font-family: monospace; color: green; }
  .priority { font-family: monospace; color: orange; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
  .underline { text-decoration: underline; }
  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  p.verse { margin-left: 3%; }
  pre {
    border: 1px solid #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  /* Languages per Org manual */
  pre.src-asymptote:before { content: 'Asymptote'; }
  pre.src-awk:before { content: 'Awk'; }
  pre.src-C:before { content: 'C'; }
  /* pre.src-C++ doesn't work in CSS */
  pre.src-clojure:before { content: 'Clojure'; }
  pre.src-css:before { content: 'CSS'; }
  pre.src-D:before { content: 'D'; }
  pre.src-ditaa:before { content: 'ditaa'; }
  pre.src-dot:before { content: 'Graphviz'; }
  pre.src-calc:before { content: 'Emacs Calc'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-fortran:before { content: 'Fortran'; }
  pre.src-gnuplot:before { content: 'gnuplot'; }
  pre.src-haskell:before { content: 'Haskell'; }
  pre.src-hledger:before { content: 'hledger'; }
  pre.src-java:before { content: 'Java'; }
  pre.src-js:before { content: 'Javascript'; }
  pre.src-latex:before { content: 'LaTeX'; }
  pre.src-ledger:before { content: 'Ledger'; }
  pre.src-lisp:before { content: 'Lisp'; }
  pre.src-lilypond:before { content: 'Lilypond'; }
  pre.src-lua:before { content: 'Lua'; }
  pre.src-matlab:before { content: 'MATLAB'; }
  pre.src-mscgen:before { content: 'Mscgen'; }
  pre.src-ocaml:before { content: 'Objective Caml'; }
  pre.src-octave:before { content: 'Octave'; }
  pre.src-org:before { content: 'Org mode'; }
  pre.src-oz:before { content: 'OZ'; }
  pre.src-plantuml:before { content: 'Plantuml'; }
  pre.src-processing:before { content: 'Processing.js'; }
  pre.src-python:before { content: 'Python'; }
  pre.src-R:before { content: 'R'; }
  pre.src-ruby:before { content: 'Ruby'; }
  pre.src-sass:before { content: 'Sass'; }
  pre.src-scheme:before { content: 'Scheme'; }
  pre.src-screen:before { content: 'Gnu Screen'; }
  pre.src-sed:before { content: 'Sed'; }
  pre.src-sh:before { content: 'shell'; }
  pre.src-sql:before { content: 'SQL'; }
  pre.src-sqlite:before { content: 'SQLite'; }
  /* additional languages in org.el's org-babel-load-languages alist */
  pre.src-forth:before { content: 'Forth'; }
  pre.src-io:before { content: 'IO'; }
  pre.src-J:before { content: 'J'; }
  pre.src-makefile:before { content: 'Makefile'; }
  pre.src-maxima:before { content: 'Maxima'; }
  pre.src-perl:before { content: 'Perl'; }
  pre.src-picolisp:before { content: 'Pico Lisp'; }
  pre.src-scala:before { content: 'Scala'; }
  pre.src-shell:before { content: 'Shell Script'; }
  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
  /* additional language identifiers per "defun org-babel-execute"
       in ob-*.el */
  pre.src-cpp:before  { content: 'C++'; }
  pre.src-abc:before  { content: 'ABC'; }
  pre.src-coq:before  { content: 'Coq'; }
  pre.src-groovy:before  { content: 'Groovy'; }
  /* additional language identifiers from org-babel-shell-names in
     ob-shell.el: ob-shell is the only babel language using a lambda to put
     the execution function name together. */
  pre.src-bash:before  { content: 'bash'; }
  pre.src-csh:before  { content: 'csh'; }
  pre.src-ash:before  { content: 'ash'; }
  pre.src-dash:before  { content: 'dash'; }
  pre.src-ksh:before  { content: 'ksh'; }
  pre.src-mksh:before  { content: 'mksh'; }
  pre.src-posh:before  { content: 'posh'; }
  /* Additional Emacs modes also supported by the LaTeX listings package */
  pre.src-ada:before { content: 'Ada'; }
  pre.src-asm:before { content: 'Assembler'; }
  pre.src-caml:before { content: 'Caml'; }
  pre.src-delphi:before { content: 'Delphi'; }
  pre.src-html:before { content: 'HTML'; }
  pre.src-idl:before { content: 'IDL'; }
  pre.src-mercury:before { content: 'Mercury'; }
  pre.src-metapost:before { content: 'MetaPost'; }
  pre.src-modula-2:before { content: 'Modula-2'; }
  pre.src-pascal:before { content: 'Pascal'; }
  pre.src-ps:before { content: 'PostScript'; }
  pre.src-prolog:before { content: 'Prolog'; }
  pre.src-simula:before { content: 'Simula'; }
  pre.src-tcl:before { content: 'tcl'; }
  pre.src-tex:before { content: 'TeX'; }
  pre.src-plain-tex:before { content: 'Plain TeX'; }
  pre.src-verilog:before { content: 'Verilog'; }
  pre.src-vhdl:before { content: 'VHDL'; }
  pre.src-xml:before { content: 'XML'; }
  pre.src-nxml:before { content: 'XML'; }
  /* add a generic configuration mode; LaTeX export needs an additional
     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
  pre.src-conf:before { content: 'Configuration File'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.org-right  { text-align: center;  }
  th.org-left   { text-align: center;   }
  th.org-center { text-align: center; }
  td.org-right  { text-align: right;  }
  td.org-left   { text-align: left;   }
  td.org-center { text-align: center; }
  dt { font-weight: bold; }
  .footpara { display: inline; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .equation-container {
    display: table;
    text-align: center;
    width: 100%;
  }
  .equation {
    vertical-align: middle;
  }
  .equation-label {
    display: table-cell;
    text-align: right;
    vertical-align: middle;
  }
  .inlinetask {
    padding: 10px;
    border: 2px solid gray;
    margin: 10px;
    background: #ffffcc;
  }
  #org-div-home-and-up
   { text-align: right; font-size: 70%; white-space: nowrap; }
  textarea { overflow-x: auto; }
  .linenr { font-size: smaller }
  .code-highlighted { background-color: #ffff00; }
  .org-info-js_info-navigation { border-style: none; }
  #org-info-js_console-label
    { font-size: 10px; font-weight: bold; white-space: nowrap; }
  .org-info-js_search-highlight
    { background-color: #ffff00; color: #000000; font-weight: bold; }
  .org-svg { width: 90%; }
  /*]]>*/-->
</style>
<style type="text/css">#table-of-contents h2 { display: none } .title { display: none } .authorname { text-align: right }</style>
<style type="text/css">.outline-2 {border-top: 1px solid black;}</style>
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2019 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.


@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">OCaml Weekly News</h1>
<p>
<a href="http://alan.petitepomme.net/cwn/2020.01.07.html">Previous Week</a> <a href="http://alan.petitepomme.net/cwn/index.html">Up</a> <a href="http://alan.petitepomme.net/cwn/2020.01.21.html">Next Week</a>
</p>

<p>
Hello
</p>

<p>
Here is the latest OCaml Weekly News, for the week of January 07 to 14, 2020.
</p>

<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#1">Calling a single function on every member of a GADT?</a></li>
<li><a href="#2">OCamlPro's opam cheat sheet, with a new theme!</a></li>
<li><a href="#3">OCaml 4.10.0, first beta</a></li>
<li><a href="#4">Data engineer positions at Elastic, US/Canada/Western Europe (proximate to NA timezones)</a></li>
<li><a href="#5">Release of naboris 0.1.0 a simple http server</a></li>
<li><a href="#6">esy@0.6.0 release</a></li>
<li><a href="#orgfbe0b31">Old CWN</a></li>
</ul>
</div>
</div>


<div id="outline-container-org3aaa880" class="outline-2">
<h2 id="1">Calling a single function on every member of a GADT?</h2>
<div class="outline-text-2" id="text-1">
<p>
Archive: <a href="https://sympa.inria.fr/sympa/arc/caml-list/2020-01/msg00007.html">https://sympa.inria.fr/sympa/arc/caml-list/2020-01/msg00007.html</a>
</p>
</div>

<div id="outline-container-org63ec34f" class="outline-3">
<h3 id="org63ec34f">Ivan Gotovchits asked</h3>
<div class="outline-text-3" id="text-org63ec34f">
<p>
I'm basically trying to do the equivalent of this simple <code>fold</code> function:
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">module</span> <span style="color: #228b22;">Simple</span> =
<span style="color: #000000; font-weight: bold;">struct</span>
  <span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">term</span> =
     | <span style="color: #000000; background-color: #ffffff;">Int</span> <span style="color: #a020f0;">of</span> int
     | <span style="color: #000000; background-color: #ffffff;">Add</span>
     | <span style="color: #000000; background-color: #ffffff;">App</span> <span style="color: #a020f0;">of</span> term * term

  <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #000000; font-weight: bold;">rec</span> <span style="color: #0000ff;">fold</span> <span style="color: #a0522d;">i</span> <span style="color: #a0522d;">f</span> = <span style="color: #a020f0;">function</span>
    | <span style="color: #000000; background-color: #ffffff;">Int</span> _ <span style="color: #a020f0;">as</span> t -&gt; f i t
    | <span style="color: #000000; background-color: #ffffff;">Add</span> -&gt; f i <span style="color: #000000; background-color: #ffffff;">Add</span>
    | <span style="color: #000000; background-color: #ffffff;">App</span> (x, y) <span style="color: #a020f0;">as</span> t -&gt; f (fold (fold i f x) f y) t
<span style="color: #000000; font-weight: bold;">end</span>
</pre>
</div>

<p>
&#x2026; but using a GADT:
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">module</span> <span style="color: #228b22;">Gadt</span> =
<span style="color: #000000; font-weight: bold;">struct</span>
  <span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">_ term</span> =
     | <span style="color: #000000; background-color: #ffffff;">Int</span> : int -&gt; int term
     | <span style="color: #000000; background-color: #ffffff;">Add</span> : (int -&gt; int -&gt; int) term
     | <span style="color: #000000; background-color: #ffffff;">App</span> : ('b -&gt; 'a) term * 'b term -&gt; 'a term

  <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #000000; font-weight: bold;">rec</span> <span style="color: #0000ff;">fold</span> :<span style="color: #228b22;"> </span><span style="color: #a020f0;">type</span><span style="color: #228b22;"> a. 'r -&gt; ('r -&gt; _ term -&gt; 'r) -&gt; 'r </span>= <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">i</span> <span style="color: #a0522d;">f</span> -&gt; <span style="color: #a020f0;">function</span>
    | <span style="color: #000000; background-color: #ffffff;">Int</span> _ <span style="color: #a020f0;">as</span> t -&gt; f i t
    | <span style="color: #000000; background-color: #ffffff;">Add</span> -&gt; f i <span style="color: #000000; background-color: #ffffff;">Add</span>
<span style="color: #b22222;">(*</span>
<span style="color: #b22222;">     ^ Error: This pattern matches values of type (int -&gt; int -&gt; int) term</span>
<span style="color: #b22222;">        but a pattern was expected which matches values of type int term</span>
<span style="color: #b22222;">        Type int -&gt; int -&gt; int is not compatible with type int</span>
<span style="color: #b22222;">*)</span>
    | <span style="color: #000000; background-color: #ffffff;">App</span> (x, y) <span style="color: #a020f0;">as</span> t -&gt; f (fold (fold i f x) f y) t
<span style="color: #000000; font-weight: bold;">end</span>
</pre>
</div>

<p>
I've tried other variants of the syntax and got many encouragements but no green flag from the type-checker.
Why is the compiler expecting an int term in there? I though the whole point of the <code>type a. ...</code> syntax was to allow the matched type to vary from one pattern to the next?
Is there a way to do this?
</p>
</div>
</div>


<div id="outline-container-orgc11829a" class="outline-3">
<h3 id="orgc11829a">Ivan Gotovchits replied</h3>
<div class="outline-text-3" id="text-orgc11829a">
<p>
It is the limitation of the let-bound polymorphism. A parameter of a
function is monomorphic in its body. The classical example doesn't even
reference any GADT,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">example</span> <span style="color: #a0522d;">f</span>  = f <span style="color: #8b2252;">"hello"</span>, f 42
</pre>
</div>

<p>
It won't compile even though we can provide a polymorphic function that can
applied both to integers and to strings, e.g., <code>exampe (fun x -&gt; x)</code> should
be possible, but not, because of the let-bounded polymorphism. There are a
few solutions available in OCaml, the simplest is to use records, e.g.,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">app</span> = {apply : 'a. 'a -&gt; 'a}

<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">example</span> {<span style="color: #a0522d;">apply</span>} = apply <span style="color: #8b2252;">"hello"</span>, apply 42<span style="color: #ff4500;">;;</span>

<span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">example</span> : app -&gt; string * int = &lt;<span style="color: #a020f0;">fun</span>&gt;
</pre>
</div>

<p>
Now we have <code>app</code> that is polymorphic.
In your case, I would define a visitor type, e.g.,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">'r visitor</span> = {visit : 'a. 'a term -&gt; 'r -&gt; 'r}

<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #000000; font-weight: bold;">rec</span> <span style="color: #a0522d;">fold</span> :<span style="color: #228b22;"> </span><span style="color: #a020f0;">type</span><span style="color: #228b22;"> a. 'r -&gt; 'r visitor -&gt; a term -&gt; 'r </span>=
  <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">i</span> <span style="color: #a0522d;">f</span> <span style="color: #a0522d;">t</span> -&gt; <span style="color: #a020f0;">match</span> t <span style="color: #a020f0;">with</span>
    | <span style="color: #000000; background-color: #ffffff;">Int</span> _ <span style="color: #a020f0;">as</span> t -&gt; f.visit i t
    | <span style="color: #000000; background-color: #ffffff;">Add</span> <span style="color: #a020f0;">as</span> t -&gt; f.visit i t
    | <span style="color: #000000; background-color: #ffffff;">App</span> (x,y) <span style="color: #a020f0;">as</span> t -&gt;
        <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">i</span> = fold i f x <span style="color: #000000; font-weight: bold;">in</span>
        <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">i</span> = fold i f y <span style="color: #000000; font-weight: bold;">in</span>
        f.visit i t
</pre>
</div>
</div>
</div>


<div id="outline-container-org525c0e6" class="outline-3">
<h3 id="org525c0e6">Jacques Garrigue also replied</h3>
<div class="outline-text-3" id="text-org525c0e6">
<p>
Actually, this is a rare case where using a polymorphic method may be
handy too:
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #000000; font-weight: bold;">rec</span> <span style="color: #a0522d;">fold</span> : <span style="color: #a020f0;">type</span> <span style="color: #228b22;">a</span> <span style="color: #a0522d;">r</span>. <span style="color: #a0522d;">r</span> -&gt; &lt;<span style="color: #a0522d;">v</span> :<span style="color: #228b22;"> 'b. r -&gt; 'b term -&gt; r&gt; -&gt; a term -&gt; r </span>=
     <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">i</span> <span style="color: #a0522d;">f</span> -&gt; <span style="color: #a020f0;">function</span>
     | <span style="color: #000000; background-color: #ffffff;">Int</span> _ <span style="color: #a020f0;">as</span> t -&gt; f#v i t
     | <span style="color: #000000; background-color: #ffffff;">Add</span> -&gt; f#v i <span style="color: #000000; background-color: #ffffff;">Add</span>
     | <span style="color: #000000; background-color: #ffffff;">App</span> (x, y) <span style="color: #a020f0;">as</span> t -&gt; f#v (fold (fold i f x) f y) t

<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">v</span> =
   <span style="color: #000000; font-weight: bold;">object</span> <span style="color: #000000; font-weight: bold;">method</span> <span style="color: #0000ff;">v</span> :<span style="color: #228b22;"> </span><span style="color: #a020f0;">type</span><span style="color: #228b22;"> a. _ -&gt; a </span><span style="color: #228b22;">Gadt.</span><span style="color: #228b22;">term -&gt; _ </span>=
     <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">x</span> -&gt; <span style="color: #a020f0;">function</span>
       | <span style="color: #000000; background-color: #ffffff;">Int</span> n -&gt; x+n
       | <span style="color: #000000; background-color: #ffffff;">Add</span> -&gt; x+1
       | <span style="color: #000000; background-color: #ffffff;">App</span> _ -&gt; x+2
   <span style="color: #000000; font-weight: bold;">end</span>

<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">r</span> = <span style="color: #228b22;">Gadt.</span>fold 0 v (<span style="color: #000000; background-color: #ffffff;">App</span> (<span style="color: #000000; background-color: #ffffff;">App</span> (<span style="color: #000000; background-color: #ffffff;">Add</span>, <span style="color: #000000; background-color: #ffffff;">Int</span> 3), <span style="color: #000000; background-color: #ffffff;">Int</span> 5))
</pre>
</div>

<p>
The point being that to match on a Gadt you will anyway need to use the
(type a) construct to allow refinement.
</p>
</div>
</div>


<div id="outline-container-orgc7f929e" class="outline-3">
<h3 id="orgc7f929e">rixed asked and Ivan Gotovchits replied</h3>
<div class="outline-text-3" id="text-orgc7f929e">
<blockquote>
<p>
So there is no lighter syntax to specify that <code>f</code> should accept any member
of a GADT than the syntax to specify that <code>f</code> should accept any type at all?
</p>
</blockquote>

<p>
Only three methods of introducing rank-2 polymorphism are known to me:
</p>
<ol class="org-ol">
<li>records</li>
<li>objects</li>
<li>first-class modules</li>
</ol>

<p>
Jacques has demonstrated the solution with objects, which might be a little
bit more lightweight, at least as you don't need to define a new data type
beforehand. But the invocation is more verbose and requires an annotation
from the caller side, which could be confusing. The third solution relies
on first-class modules and is even more verbose, at least on the definition
side. Just for the sake of completeness,
</p>

<div class="org-src-container">
<pre class="src src-ocaml">  <span style="color: #000000; font-weight: bold;">module type</span> <span style="color: #228b22;">Visitor</span> = <span style="color: #000000; font-weight: bold;">sig</span>
    <span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">t</span>
    <span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">term</span> : t -&gt; 'a term -&gt; t
  <span style="color: #000000; font-weight: bold;">end</span>

  <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #000000; font-weight: bold;">rec</span> <span style="color: #a0522d;">fold</span> :<span style="color: #228b22;"> </span><span style="color: #a020f0;">type</span><span style="color: #228b22;"> a r. r -&gt; (</span><span style="color: #000000; font-weight: bold;">module</span><span style="color: #228b22;"> </span><span style="color: #228b22;">Visitor</span><span style="color: #228b22;"> </span><span style="color: #000000; font-weight: bold;">with type</span><span style="color: #228b22;"> t </span>= r) -&gt; a term
-&gt; r =
    <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">i</span> ((<span style="color: #a020f0;">module</span> <span style="color: #228b22;">Visit</span>) <span style="color: #a020f0;">as</span> <span style="color: #a0522d;">f</span>) <span style="color: #a0522d;">t</span> -&gt; <span style="color: #a020f0;">match</span> t <span style="color: #a020f0;">with</span>
      | <span style="color: #000000; background-color: #ffffff;">Int</span> _ <span style="color: #a020f0;">as</span> t -&gt; <span style="color: #228b22;">Visit.</span>term i t
      | <span style="color: #000000; background-color: #ffffff;">Add</span> <span style="color: #a020f0;">as</span> t -&gt; <span style="color: #228b22;">Visit.</span>term i t
      | <span style="color: #000000; background-color: #ffffff;">App</span> (x,y) <span style="color: #a020f0;">as</span> t -&gt;
          <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">i</span> = fold i f x <span style="color: #000000; font-weight: bold;">in</span>
          <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">i</span> = fold i f y <span style="color: #000000; font-weight: bold;">in</span>
          <span style="color: #228b22;">Visit.</span>term i t

  <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">s</span> = fold 0 (<span style="color: #000000; font-weight: bold;">module</span> <span style="color: #000000; font-weight: bold;">struct</span>
      <span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">t</span> = int
      <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">term</span> <span style="color: #a0522d;">x</span> <span style="color: #a0522d;">_</span> = x + 1
    <span style="color: #000000; font-weight: bold;">end</span>)
</pre>
</div>

<p>
And again, it is not about GADT. GADT act as a red herring here. As I've
demonstrated earlier, using a simple pair will suffice to display the
limitation of the prenex polymorphism. Even no ADT is required, just apply
one term to another two and you will get them unified, e.g.,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">f</span> <span style="color: #a0522d;">g</span> <span style="color: #a0522d;">x</span> <span style="color: #a0522d;">y</span> :<span style="color: #228b22;"> unit </span>= g x; g y
</pre>
</div>

<p>
will have type
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">f</span> : ('a -&gt; unit) -&gt; 'a -&gt; 'a -&gt; unit
</pre>
</div>

<p>
because 'a is quantified on the scope of <code>f</code> not <code>g</code>, in other words, it
has type (not an OCaml syntax)
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">f</span> : forall 'a. ('a -&gt; unit) -&gt; 'a -&gt; 'a -&gt; unit
</pre>
</div>

<p>
while we would like to have a type
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">f</span> : forall 'b, 'c. (forall 'a. 'a -&gt; unit) -&gt; 'b -&gt; 'c -&gt; unit
</pre>
</div>

<p>
OCaml doesn't allow us to define types like <code>('a. 'a -&gt; 'a)</code> and the reason
is not that it is hard to extend the parser it is&#x2026;
</p>

<blockquote>
<p>
I wonder, is this just a limitation of the OCaml parser or is there some
deep reason for these work-around (like is the case, from my understanding,
for the value restriction)?
</p>
</blockquote>

<p>
Yep, good catch! It is because of the impurity. Indeed, Haskell has the
Rank2Types extension that lets us write types like <code>(forall a. a -&gt; ()) -&gt;
b -&gt; c -&gt; ()</code>, with no extra syntactic burden (modulo having to provide the
type annotation). But functions in Haskell are pure, therefore it is
possible. To make the story short and obvious, let me do a simple
demonstration of how things can go wrong in a language with side-effects.
Let's go back to the simple example of pairs and the identity function.
Consider the following nasty identity function,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">bad_id</span> () =
  <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">cache</span> = <span style="color: #483d8b;">ref</span> <span style="color: #000000; background-color: #ffffff;">None</span> <span style="color: #000000; font-weight: bold;">in</span>
  <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">x</span> -&gt; <span style="color: #a020f0;">match</span> cache.contents <span style="color: #a020f0;">with</span>
    | <span style="color: #000000; background-color: #ffffff;">None</span> -&gt; cache := <span style="color: #000000; background-color: #ffffff;">Some</span> x; x
    | <span style="color: #000000; background-color: #ffffff;">Some</span> cache -&gt; cache
</pre>
</div>

<p>
It has type <code>unit -&gt; 'a -&gt; 'a</code> therefore, if we would have the rank-1
polymorphism enabled for functions, we could apply it to the function
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">map2</span> :<span style="color: #228b22;"> </span><span style="color: #a020f0;">fun</span><span style="color: #228b22;"> ('a. 'a -&gt; 'a) -&gt; 'b -&gt; 'c -&gt; 'b * 'c </span>= <span style="color: #a020f0;">fun</span> <span style="color: #a0522d;">f</span> (<span style="color: #a0522d;">x</span>,<span style="color: #a0522d;">y</span>) -&gt; f x, f y
</pre>
</div>

<p>
as
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">x</span>,<span style="color: #a0522d;">y</span> :<span style="color: #228b22;"> string * int </span>= map2 (bad_id ()) <span style="color: #8b2252;">"hello"</span>, 42
</pre>
</div>

<p>
and will get a segmentation fault, as <code>y</code> will now have type int but hold a
string.
</p>

<p>
And here comes the syntax as a savior as it lets us specify functions that
are guaranteed to be syntactic values. Indeed, all three solutions
syntactically guarantee that the provided argument is a function, not a
closure. Indeed, let's introduce the universal identity via a record,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">id</span> = { f : 'a. 'a -&gt; 'a}
</pre>
</div>

<p>
and we can see that our <code>bad_id</code> is not accepted due to the value
restriction, while good_id, defined as,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">good_id</span> <span style="color: #a0522d;">x</span> = x
</pre>
</div>

<p>
is perfectly fine, e.g.,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">id1</span> = {f = good_id} <span style="color: #b22222;">(*</span><span style="color: #b22222;">accepted </span><span style="color: #b22222;">*)</span>
<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">id2</span> = {f = bad_id}   <span style="color: #b22222;">(* </span><span style="color: #b22222;">rejected </span><span style="color: #b22222;">*)</span>
</pre>
</div>

<p>
moreover, even a fine, but not syntactic, identity is also rejected
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">fine_id</span> () <span style="color: #a0522d;">x</span> = x
<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">id3</span> = {f = fine_id ()} <span style="color: #b22222;">(* </span><span style="color: #b22222;">rejected </span><span style="color: #b22222;">*)</span>
</pre>
</div>

<p>
with the message
</p>

<pre class="example">
This field value has type 'b -&gt; 'b which is less general than 'a. 'a -&gt; 'a
</pre>

<p>
The same is true with modules,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">module type</span> <span style="color: #228b22;">Id</span> = <span style="color: #000000; font-weight: bold;">sig</span>
  <span style="color: #000000; font-weight: bold;">val</span> <span style="color: #0000ff;">f</span> : 'a -&gt; 'a
<span style="color: #000000; font-weight: bold;">end</span>
<span style="color: #000000; font-weight: bold;">module</span> <span style="color: #228b22;">Id1</span> : <span style="color: #228b22;">Id</span> = <span style="color: #000000; font-weight: bold;">struct</span> <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">f</span> = good_id <span style="color: #000000; font-weight: bold;">end</span>   <span style="color: #b22222;">(* </span><span style="color: #b22222;">accepted </span><span style="color: #b22222;">*)</span>
<span style="color: #000000; font-weight: bold;">module</span> <span style="color: #228b22;">Id2</span> : <span style="color: #228b22;">Id</span> = <span style="color: #000000; font-weight: bold;">struct</span> <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">f</span> = bad_id () <span style="color: #000000; font-weight: bold;">end</span> <span style="color: #b22222;">(* </span><span style="color: #b22222;">rejected </span><span style="color: #b22222;">*)</span>
<span style="color: #000000; font-weight: bold;">module</span> <span style="color: #228b22;">Id3</span> : <span style="color: #228b22;">Id</span> = <span style="color: #000000; font-weight: bold;">struct</span> <span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">f</span> = fine_id () <span style="color: #000000; font-weight: bold;">end</span> <span style="color: #b22222;">(* </span><span style="color: #b22222;">rejected </span><span style="color: #b22222;">*)</span>
</pre>
</div>

<p>
and with objects (left as an exercise).
</p>

<p>
To summarize, in order to enable rank2 polymorphism we need a special kind
of values to bear universal functions, as we can't rely on ordinary
functions, which could be constructed using partial application. OCaml
already had objects and records, which serve as a fine media for
universally quantified functions. Later first class modules were
introduced, which could also be used for the same purpose. Probably, one
could devise a special syntax (or rely on the new attributes and extensions
syntax, e.g., <code>map2 [%rank2 : fun x -&gt; x] ("hello",42)</code> but probably this
will lead to an unnecessary bloating of the language and the
implementation, especially since we already have three solutions with a
more or less tolerable syntax (and are in the base language, not an
extension).  Besides, if we will use the <code>[@@unboxed]</code> annotation, or
visitor will have the same representation as a function, e.g.,
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">'r visitor</span> = {visit : 'a. 'r -&gt; 'a term -&gt; 'r} <span style="color: #483d8b;">[@@unboxed]</span>
<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #0000ff;">count</span> <span style="color: #a0522d;">x</span> <span style="color: #a0522d;">_</span> = x + 1
<span style="color: #000000; font-weight: bold;">let</span> <span style="color: #a0522d;">counter</span> = {visit=count}
</pre>
</div>

<p>
and
</p>

<div class="org-src-container">
<pre class="src src-ocaml"># <span style="color: #228b22;">Core_kernel.</span>phys_same count counter<span style="color: #ff4500;">;;</span>
- : bool = <span style="color: #008b8b;">true</span>
</pre>
</div>

<p>
Concerning rank-n polymorphism, in OCaml is is achieved using functors.
Yes, they are a little bit syntactically heavy and force us to write
signatures, but this is necessary anyway as rank-n is undecidable
(non-inferrable). Finally, as a real-world example [1] of rank-2
polymorphism consider the universal WAVL tree that is a binary tree with
each element having a different type (aka heterogeneous map). We use it in
BAP as a backing store. You might find a few tricks there, especially using
continuation-passing in the recursive cases.
</p>

<p>
Cheers,
Ivan
</p>

<p>
[1]: <a href="https://github.com/BinaryAnalysisPlatform/bap/blob/b40689e636607b977758af048b79d65684ce48c3/lib/knowledge/bap_knowledge.ml#L847-L1693">https://github.com/BinaryAnalysisPlatform/bap/blob/b40689e636607b977758af048b79d65684ce48c3/lib/knowledge/bap_knowledge.ml#L847-L1693</a>
</p>
</div>
</div>


<div id="outline-container-org97ec684" class="outline-3">
<h3 id="org97ec684">Malcolm Matalka asked and Ivan Gotovchits replied</h3>
<div class="outline-text-3" id="text-org97ec684">
<blockquote>
<p>
Why is type checking creating a record different than type checking a
function argument?
</p>

<p>
If we had the syntax (or something like it):
</p>

<p>
let map2 : ('a. 'a -&gt; 'a) -&gt; ('b * 'c) -&gt; ('b * 'c)
</p>

<p>
Why would the type checker not be able to see that
</p>

<p>
map2 good_id ("hi", 42)
</p>

<p>
is valid but
</p>

<p>
map2 (fine_id ()) ("hi", 32)
</p>

<p>
is not, using the same logic that is verifying creating the "id" record
is not valid?
</p>
</blockquote>

<p>
I believe it is possible, as it is possible in Haskell (with RankNTypes and
ScopedTypeVariables). The main (theoretical) difference is that in OCaml we
need to check whether an expression is expansive and use a specialized
generalization in case if it is (for the relaxed value restriction). It
will, however, complicate the type inference engine a lot, but most
importantly, changing the typing rule of functions will have a tremendous
impact on the language. So this would be a very impractical solution.
Especially, since we don't have the mechanism of language extensions,
enabling RankNTypes will make a lot of programs untypeable, as they will
now require type annotations (recall that RankN is undecidable in general).
It could probably be implemented as a compiler command line parameter, like
<code>-rectypes</code> but this will be still quite impractical since more often code
like <code>fun f -&gt; f 1, f true</code> is a programmer error, rather than a true
request for universal polymorphism (the same as with rectypes, recursive
types a more often an error rather than a deliberate attempt). Therefore,
enabling RankN(^1) polymorphism will type too many programs (not that it is
unsound, just many programs won't have sense) at the cost of even more
obscure type errors. On the other hand, we have three syntactic constructs
that let us express non-prenex polymorphism of the necessary rank(^2)
without breaking anything else. So it looks like a good deal - we can have
rankN polymorphism and decidable type checker at the same time. Just think
of polymorphic records/methods as an embedded DSL for rankN polymorphism.
</p>

<p>
<code>==========</code>
Footnotes:
</p>

<ol class="org-ol">
<li>An important point, that I forgot to notice, is that enabling scoped</li>
</ol>
<p>
type variables, will inevitably enable rankN polymorphism, e.g., since now
any type could be a polytype, then suppose we have type <code>'a. ('b.'b -&gt; 'a)
-&gt; 'a</code> could be instantiated to 'a = 'd. ('c. -&gt;  'd) -&gt; 'd, so that our
type is now <code>'d. ('b. 'b -&gt; ('c. 'c -&gt; 'd) -&gt; 'd) -&gt; ('c. 'c -&gt; 'd) -&gt; 'd</code>
which is now rank3. Therefore, enabling arbitrary quantification in the
arrow type will lead to rankN and immediately make undecidable most of the
type checker.
</p>

<ol class="org-ol">
<li>We can craft arbitrary rank using records with universally quantified</li>
</ol>
<p>
type variables, e.g., here is an example of rank3 polymorphism:
</p>

<div class="org-src-container">
<pre class="src src-ocaml"><span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">'a rank1</span> = {f1 : 's. 's -&gt; 'a}
<span style="color: #000000; font-weight: bold;">type</span> <span style="color: #228b22;">'a rank2</span> = {f2 : 'r. 'r -&gt; 'a rank1}
</pre>
</div>

<p>
Indeed, <code>f2</code> has type <code>'a.('r. 'r -&gt; ('s. 's -&gt; 'a)</code>
</p>
</div>
</div>
</div>




<div id="outline-container-org1ba683e" class="outline-2">
<h2 id="2">OCamlPro's opam cheat sheet, with a new theme!</h2>
<div class="outline-text-2" id="text-2">
<p>
Archive: <a href="https://discuss.ocaml.org/t/rfc-ocamlpros-opam-cheat-sheet-with-a-new-theme/4689/3">https://discuss.ocaml.org/t/rfc-ocamlpros-opam-cheat-sheet-with-a-new-theme/4689/3</a>
</p>
</div>

<div id="outline-container-org099685d" class="outline-3">
<h3 id="org099685d">Thomas Blanc announced</h3>
<div class="outline-text-3" id="text-org099685d">
<p>
The opam cheat-sheet is now published in its final form.
</p>

<p>
You can get the <a href="http://www.ocamlpro.com/wp-content/uploads/2019/11/ocaml-opam.pdf">colored</a> and <a href="http://www.ocamlpro.com/wp-content/uploads/2020/01/ocaml-opam-bw.pdf">black-and-white</a> versions from our website.
</p>

<p>
Happy hacking!
</p>
</div>
</div>
</div>




<div id="outline-container-orgbeea946" class="outline-2">
<h2 id="3">OCaml 4.10.0, first beta</h2>
<div class="outline-text-2" id="text-3">
<p>
Archive: <a href="https://discuss.ocaml.org/t/ocaml-4-10-0-first-beta/4989/1">https://discuss.ocaml.org/t/ocaml-4-10-0-first-beta/4989/1</a>
</p>
</div>

<div id="outline-container-orgf3b2516" class="outline-3">
<h3 id="orgf3b2516">octachron announced</h3>
<div class="outline-text-3" id="text-orgf3b2516">
<p>
The release of OCaml 4.10.0 is approaching. We have published
a first beta version to help you adapt your software to the new features
ahead of the release.
</p>

<p>
During our preliminary tests for this new beta, we discovered that the recent
work towards a multicore-ready OCaml runtime introduced compatibility issues
within some opam packages, that were tweaking the runtime internals.
Most of those opam packages have been fixed, or will be soon.
Nevertheless, if you are affected by such compatibility issue, please speak up.
</p>

<p>
The source code is available at these addresses:
</p>

<p>
<a href="https://github.com/ocaml/ocaml/archive/4.10.0+beta1.tar.gz">https://github.com/ocaml/ocaml/archive/4.10.0+beta1.tar.gz</a> <br />
<a href="https://caml.inria.fr/pub/distrib/ocaml-4.10/ocaml-4.10.0+beta1.tar.gz">https://caml.inria.fr/pub/distrib/ocaml-4.10/ocaml-4.10.0+beta1.tar.gz</a>
</p>

<p>
The compiler can also be installed as an OPAM switch with one of the
following commands.
</p>
<div class="org-src-container">
<pre class="src src-shell">opam switch create ocaml-variants.4.10.0+beta1 --repositories=default,<span style="color: #a0522d;">beta</span>=git+https://github.com/ocaml/ocaml-beta-repository.git
</pre>
</div>
<p>
or
</p>
<div class="org-src-container">
<pre class="src src-shell">opam switch create ocaml-variants.4.10.0+beta1+&lt;VARIANT&gt; --repositories=default,<span style="color: #a0522d;">beta</span>=git+https://github.com/ocaml/ocaml-beta-repository.git
</pre>
</div>
<p>
where you replace &lt;VARIANT&gt; with one of these:
</p>
<ul class="org-ul">
<li>afl</li>
<li>flambda</li>
<li>fp</li>
<li>fp+flambda</li>
</ul>

<p>
We want to know about all bugs. Please report them here:
</p>

<p>
<a href="https://github.com/ocaml/ocaml/issues">https://github.com/ocaml/ocaml/issues</a>
</p>

<p>
Happy hacking.
</p>
</div>
</div>


<div id="outline-container-orgb135b4c" class="outline-3">
<h3 id="orgb135b4c">Kate added</h3>
<div class="outline-text-3" id="text-orgb135b4c">
<p>
For the people wanting to give OCaml 4.10.0beta1 a shot, here is an opam overlay which adds fixes to major packages for them to work with this beta: <a href="https://github.com/kit-ty-kate/opam-alpha-repository">https://github.com/kit-ty-kate/opam-alpha-repository</a>
</p>

<p>
To use it, simple call:
</p>
<pre class="example">
$ opam switch 4.10
$ opam repository add alpha git://github.com/kit-ty-kate/opam-alpha-repository.git
</pre>

<p>
Obviously, this repository should not be used in production and probably contains a few bugs, but at least it allows everyone to have almost as many packages available as with OCaml 4.09. Only 60ish packages are still not available, but apart from the notable exception of <code>merlin</code> all the essential packages and dependencies are there.
</p>

<p>
This work has been part of the release-readyness effort founded by the OCaml Software Foundation as announced here: <a href="https://discuss.ocaml.org/t/ann-the-ocaml-software-foundation/4476/13">https://discuss.ocaml.org/t/ann-the-ocaml-software-foundation/4476/13</a>
</p>

<p>
The rest of the effort is going to be put towards having <code>merlin</code> available for OCaml 4.10 and upstreaming all the fixes from opam-alpha-repository (most of them have PRs associated already). I'm hopeful for them be all upstreamed and available before the stable release of OCaml 4.10.
</p>
</div>
</div>
</div>




<div id="outline-container-org5c9b87c" class="outline-2">
<h2 id="4">Data engineer positions at Elastic, US/Canada/Western Europe (proximate to NA timezones)</h2>
<div class="outline-text-2" id="text-4">
<p>
Archive: <a href="https://discuss.ocaml.org/t/job-data-engineer-positions-at-elastic-us-canada-western-europe-proximate-to-na-timezones/4991/1">https://discuss.ocaml.org/t/job-data-engineer-positions-at-elastic-us-canada-western-europe-proximate-to-na-timezones/4991/1</a>
</p>
</div>

<div id="outline-container-orgc096a78" class="outline-3">
<h3 id="orgc096a78">Hezekiah Carty announced</h3>
<div class="outline-text-3" id="text-orgc096a78">
<p>
Our team here at <a href="https://www.elastic.co/">Elastic</a> has positions open for a few security data engineers (aka wranglers of data and all the systems involved).  We are a distributed company so you don't have to be close to an office to be considered.  Infosec industry experience is <span class="underline">not</span> required, though of course welcome.  We're surrounded by experts in the field so you'll have lots of opportunities to learn as you go!
</p>

<p>
The official postings are available here (both have the same text and only differ in title/seniority):
</p>
<ul class="org-ul">
<li>Security data engineer - <a href="https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-data-engineer/2005140#/">https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-data-engineer/2005140#/</a></li>
<li>Senior security data engineer - <a href="https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-senior-data-engineer/2005152#/">https://jobs.elastic.co/jobs/security-solutions/amer-distributed-/security-senior-data-engineer/2005152#/</a></li>
</ul>

<p>
Language-wise, OCaml/Reason makes up most of the code you’ll be working on. Python makes up most of the rest, in particular taking advantage of the machine learning and natural language processing goodies that ecosystem provides. Most of the tools and service we develop are internally focused, supporting security research and improvements to security protections for our users. For those so-inclined, there are lots of opportunities to present at and attend conferences, present work in blog posts, contribute to open source software projects and otherwise engage the community.
</p>

<p>
The positions are very similar to our <a href="https://discuss.ocaml.org/t/filled-posting-is-no-longer-open-threat-research-engineer-job-endgame-us/1937">last hiring announcement</a>, though we had a different name at that point!
</p>

<p>
Please reach out to me if you have any questions. I’m available on the OCaml or Reason Discord servers or by email at hezekiah.carty@elastic.co.
</p>
</div>
</div>
</div>




<div id="outline-container-org605ec9a" class="outline-2">
<h2 id="5">Release of naboris 0.1.0 a simple http server</h2>
<div class="outline-text-2" id="text-5">
<p>
Archive: <a href="https://discuss.ocaml.org/t/release-of-naboris-0-1-0-a-simple-http-server/4994/1">https://discuss.ocaml.org/t/release-of-naboris-0-1-0-a-simple-http-server/4994/1</a>
</p>
</div>

<div id="outline-container-org4f37162" class="outline-3">
<h3 id="org4f37162">Shawn McGinty announced</h3>
<div class="outline-text-3" id="text-org4f37162">
<p>
<a href="https://github.com/shawn-mcginty/naboris">https://github.com/shawn-mcginty/naboris</a>
</p>

<p>
I could use input on the API and the documentation.  Working on trying to improve both at the moment.
</p>

<p>
The goal was to create a very simple library for building RESTful type of web servers.  Make it <span class="underline">very</span> easy to manage handle request/response lifecycle and sessions.
</p>

<p>
In my opinion this type of web server is a great entry point for new developers looking to explore the OCaml/Reason world.
</p>

<p>
Recently I have fallen in love with OCaml and Reason, and as a mostly web centered developer I've found this area quite lacking.  I'm still new to the language and eco system so any guidance would be highly appreciated!
</p>
</div>
</div>


<div id="outline-container-org268713b" class="outline-3">
<h3 id="org268713b">Yawar Amin replied</h3>
<div class="outline-text-3" id="text-org268713b">
<p>
Wow! It seems we had much the same idea–OCaml/Reason more accessible to web developers new to the ecosystem :-D I've been working on something very similar: <a href="https://github.com/yawaramin/re-web/">https://github.com/yawaramin/re-web/</a>
</p>
</div>
</div>


<div id="outline-container-orga9b9c7d" class="outline-3">
<h3 id="orga9b9c7d">Ulrik Strid said</h3>
<div class="outline-text-3" id="text-orga9b9c7d">
<p>
There is also opium <a href="https://github.com/rgrinberg/opium">https://github.com/rgrinberg/opium</a>
</p>

<p>
And morph <a href="https://github.com/reason-native-web/morph">https://github.com/reason-native-web/morph</a> that has similar goals.
</p>

<p>
It would be nice if we could either create a shared core that all could build from or collaborate on one.
</p>
</div>
</div>
</div>




<div id="outline-container-orga7a2c90" class="outline-2">
<h2 id="6">esy@0.6.0 release</h2>
<div class="outline-text-2" id="text-6">
<p>
Archive: <a href="https://discuss.ocaml.org/t/ann-esy-0-6-0-release/5010/1">https://discuss.ocaml.org/t/ann-esy-0-6-0-release/5010/1</a>
</p>
</div>

<div id="outline-container-orgd5a6426" class="outline-3">
<h3 id="orgd5a6426">Andrey Popp announced</h3>
<div class="outline-text-3" id="text-orgd5a6426">
<p>
We've just released a new version of esy. You can install it with npm:
</p>
<pre class="example">
$ npm install -g esy@0.6.0
</pre>

<p>
<a href="https://esy.sh">esy</a> is a package.json driven workflow for native development with Reason/OCaml (and even C/C++). It provides per-project build environments which are isolated from each other but share underlying build caches so creating new environments is cheap.
</p>

<p>
While 0.6.0 is mainly about "quality-of-life" improvements it also got few new features including a basic support for garbage collection of unused build artifacts.
</p>

<p>
For more info see a <a href="https://esy.sh/blog/2020/01/12/0.6.0.html">blog post</a> by @prometheansacrifice which highlights important updates in 0.6.0.
</p>
</div>
</div>
</div>




<div id="outline-container-orgfbe0b31" class="outline-2">
<h2 id="orgfbe0b31">Old CWN</h2>
<div class="outline-text-2" id="text-orgfbe0b31">
<p>
If you happen to miss a CWN, you can <a href="mailto:alan.schmitt@polytechnique.org">send me a message</a> and I'll mail it to you, or go take a look at <a href="http://alan.petitepomme.net/cwn/">the archive</a> or the <a href="http://alan.petitepomme.net/cwn/cwn.rss">RSS feed of the archives</a>.
</p>

<p>
If you also wish to receive it every week by mail, you may subscribe <a href="http://lists.idyll.org/listinfo/caml-news-weekly/">online</a>.
</p>

<div class="authorname">
<p>
<a href="http://alan.petitepomme.net/">Alan Schmitt</a>
</p>

</div>
</div>
</div>
</div>
</body>
</html>


             reply index

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-14 14:16 Alan Schmitt [this message]
  -- strict thread matches above, loose matches on Subject: below --
2020-01-21 14:08 Alan Schmitt
2020-01-07 13:43 Alan Schmitt
2019-12-31  9:18 Alan Schmitt
2019-12-17  8:52 Alan Schmitt
2019-12-10  8:21 Alan Schmitt
2019-12-03 15:42 Alan Schmitt
2019-11-26  8:33 Alan Schmitt
2019-11-12 13:21 Alan Schmitt
2019-11-05  6:55 Alan Schmitt
2019-10-15  7:28 Alan Schmitt
2019-09-03  7:35 Alan Schmitt

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pnfmt963.fsf@polytechnique.org \
    --to=alan.schmitt@polytechnique.org \
    --cc=caml-list@inria.fr \
    --cc=cwn@lists.idyll.org \
    --cc=lwn@lwn.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

caml-list - the Caml user's mailing list

Archives are clonable:
	git clone --mirror http://inbox.vuxu.org/caml-list
	git clone --mirror https://inbox.ocaml.org/caml-list

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.caml-list


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git