OCaml Weekly News

Previous Week Up Next Week

Hello

Here is the latest OCaml Weekly News, for the week of August 22 to 29, 2023.

Table of Contents

How suitable is OCaml for full stack web development?

bememol asked

I’m looking into getting more into a full stack web development. I do lots and lots of backend services but I really would like to cross the region to the frontend as well and I would like to avoid as much JS as possible. Htmx caught my attention but I still need some frontend code for more dynamic parts of my webapp. This can be pure JS or wasm. How does OCaml perform at this kind of situation? My ideal scenario would be something like OCaml + Htmx for most pages and at some pages some kind of compilation to JS or wasm for the dynamic parts.

Yawar Amin replied

I recommend checking out my library to write HTM especially as it ships with the htmx attributes out of the box: https://github.com/yawaramin/dream-html

If you want to compile to JS, there are a couple of options. The first and simplest one you should probably look at is ReScript. It’s an OCaml derivative that has been modified to look more like TypeScript while keeping the compile speed and type safety of OCaml. There are a couple of other options but I’ll let others give details about those.

Lastly, for slightly more client-side interaction than what htmx does, check out AlpineJS, which is a library which uses attributes similar to htmx but is frontend only. It can probably give you a lot more functionality with very little custom-written JS.

Daniel Bünzli then said

The first and simplest one you should probably look at is ReScript.

Well if you want to do full stack development in OCaml you probably don’t want to add yet another language. So the “first and simplest” would rather be to use: js_of_ocaml which is a very stable and funded OCaml to JavaScript compiler closely following the latest compiler developments.

However if you don’t want to lose your time I’d personally advise to steer away from js_of_ocaml FFI and browser APIs and use brr instead which is an order of magnitude more ergonomic and documented. But I’m biased.

Also if you want to get an idea on how that could look like you can have a look here (though I’m not happy with all the way the code looks like there :-). This is a fully working and actively used application that closely matches the description of what you are after. It’s a basic CRUD app not using htmx but a derivative that tries to address some of its shortcomings, along with a little tiny bit of custom front end code. Though they will eventually be, not every library I’m using there is formally distributed yet, so you may have to use other components but it can give you an idea.

Vincent Balat also replied

The Ocsigen project provides a full set of tools for full stack Web development, among which:

  • Js_of_ocaml, a compiler from OCaml to JS
  • Eliom, a 100% full stack Web framework (traditional Web programming + integrated client/server programming, generation of pages either on server or client, mobile apps for Android and iOS)
  • Ocsigen Toolkit, a set of client-server widgets for Web and mobile applications

The project is mature and used by real world applications (especially Be Sport).

You can find the main documentation here

Xavier Van de Woestyne also replied

And, a little shameless plug, we are currently developing a minimalist solution (based on several proven building blocks from the OCaml community) for building web applications with OCaml, easily:

  • https://github.com/funkywork/nightmare which covers the backend (currently, above Dream) and the frontend (above Js_of_ocaml and an overlay to OCaml-vdom and Tyxml) which allows you to quickly create APIs and clients (we are currently working on the abstraction of forms)
  • https://github.com/funkywork/yourbones Even if it’s not entirely related to web development, blockchains can act as a 4th tier, and this library (WIP) works well with Nightmare to interact with Tezos (example).

Last year, we developed a forum in OCaml: https://github.com/xvw/muhokama Last year, we developed a forum in OCaml: https://github.com/xvw/muhokama which proves that OCaml is perfectly suited to web development, and the proposals made by my predecessors show that in addition to being suited, OCaml is effective (I know of few frameworks as ambitious as Ocsigen for example, which at the time and still today is particularly revolutionary).

psb also replied

Caqti 2.0.1

Petter A. Urkedal announced

I am happy to announce the release of Caqti 2.0.1. Caqti is an abstraction over multiple database client libraries, providing a unified approach to passing parameters and decoding result rows, but otherwise more low level than object-relational mappers like SQLAchemy.

This is the first OPAM release in the 2.0 series. It includes experimental EIO and MirageOS support. The latter depends on the PGX pure-OCaml PostgreSQL library, and work for upcoming minor releases like TLS support should make it feasible for production use. Other changes to note is the addition of printf-style query-string construction contributed by Basile Clément, and better record and tuple handling. The full list of changes can be found in the release notes for Caqti 2.0.0.

I would like to thank the OCaml Software Foundation for the economic support, and everyone who have contributed with code or documentation, or helped identify issues.

Lwt.5.7.0

Raphaël Proust announced

It is a pleasure to announce the release of Lwt version 5.7.0. This release fixes some compatibility issues with OCaml 5, removes some deprecated functions, and offers new features to improve exception management in downstream user code.

https://github.com/ocsigen/lwt/releases/tag/5.7.0

Thank you to all the contributors who participate in the development of Lwt.

Check out the release page for a full list of changes, including breaking API changes.

Release of ocaml-sf/learn-ocaml:0.15.0

Erik Martin-Dorel announced

We are pleased to announce the latest stable release of Learn-OCaml , version 0.15.0.

Many thanks to all users who contributed bugs reports, fixes, and enhancements!

A comprehensive list of the fixes and enhancements offered by this release is available in the Release Notes with also gathers static binaries for Linux and macOS, the corresponding opam-repository pull request is pending, and the Docker images of learn-ocaml and learn-ocaml-client are immediately available on Docker hub

If you happen to maintain a learn-ocaml server, we strongly recommend that you update your version to 0.15.0 to benefit from important fixes (including a path traversal vulnerability fix), as well as newest features.

>From a teacher point-of-view, this release improves the UI/UX for the “teacher tab” as well as the “partition view” pages.

If need be, feel free to open issues in the Learn-OCaml bug tracker or the learn-ocaml.el bug tracker, or post in this thread to share comments.

Happy OCaml learning and teaching, and stay tuned for the next release!

First release of opam-check-npm-deps plugin 1.0.0

Javier Chávarri announced

I am happy to announce on behalf of the Ahrefs and Melange teams the first release 1.0.0 of the opam-check-npm-deps opam plugin.

This plugin aims to solve a simple limitation: how to allow libraries written for either Melange or Js_of_ocaml to define dependencies to JavaScript packages. It addresses the problem by enabling library authors to leverage the depexts field in opam files to define dependencies on npm packages.

For library authors: defining constraints

Constraints are defined by adding an entry to depexts with the npm package name as the “system package” and an equality formula that matches the npm-version variable to a version range. This range can be defined using the same format as the dependencies field in a package.json file [^1].

For example, the reason-react bindings can define their dependency on the react and react-dom npm packages like this:

depexts: [
  ["react"] {npm-version = "^16.0.0 || ^17.0.0"}
  ["react-dom"] {npm-version = "^16.0.0 || ^17.0.0"}
]

Or, to simplify:

depexts: [
  ["react" "react-dom"] {npm-version = "^16.0.0 || ^17.0.0"}
]

For library users: checking npm dependencies status

Users can check the state of the npm dependencies by running the plugin:

$ opam-check-npm-deps
Ok: opam package "test.dev" requires npm package: "react" with constraint "^16.0.0 || ^17.0.0", version installed:
"17.0.2"
Ok: opam package "test.dev" requires npm package: "react-dom" with constraint "^16.0.0 || ^17.0.0", version
installed: "17.0.2"

The plugin will provide information when errors occur:

$ opam-check-npm-deps
Error: opam package "test.dev" requires npm package "react" with constraint "^16.0.0 || ^17.0.0", but the version
installed found in file "node_modules/react/package.json" is "18.2.0"
Error: opam package "test.dev" requires npm package "react-dom" with constraint "^16.0.0 || ^17.0.0", but the
version installed found in file "node_modules/react-dom/package.json" is "18.2.0"

When running the plugin, it checks the current opam switch to read all depexts fields that use the npm-version variable, and then reads the node_modules folder to determine if the constraints are satisfied.

Compatibility

The plugin is currently compatible with version 2.1 of opam.

Upcoming plans and ecosystem collaboration

Our next steps will involve testing this initial version with Melange libraries and projects, and gathering feedback from the community about use cases and functionality. We will also keep an eye on the release of opam 2.2 for an upgrade. If you have suggestions about how to improve the plugin or find any bugs, please open an issue in the project repository.

It is exciting to release a tool that can be useful for both Js_of_ocaml and Melange developers. I hope that both ecosystems discover more areas for potential convergence in the future.

Happy coding!

[^1]: Special thanks to the esy authors and contributors, as the plugin reuses many of esy’s libraries to analyze constraints in a format compatible with package.json files.

Deploy dream on railway.app via template

Dennis Dang announced

Heyo, sharing this template I made to deploy dream apps on https://railway.app.

https://railway.app/template/mxESzS

Shared it in the ocamllabs slack, and figured it could be helpful here too. I’ve been throwing my experiments with ocaml+dream onto railway because their $5 USD/mo hobby tier fits me best. Fly.io works but it’s annoying having to setup github ci per new idea, and then Render costs $7/mo/project. Railway charges based on usage, similar to Fly.io.

Full disclosure: if you deploy with the template and end up subscribing, I believe I get hosting credits. But you don’t have to do that! Just fork the linked github repo, and deploy it on your own.

Doc Review: Updating S-Expressions Tutorial

Christine announced

We’ve been working on updating and improving the Learn documents on OCaml.org, and we would love your help and feedback in reviewing them.

https://github.com/ocaml/ocaml.org/pull/1507

Did we miss anything? Does something need clarification?

We’re also still hoping for feedback and comments on the updated Getting Started documents: A Tour of OCaml and How to Write an OCaml Program. The Install OCaml tutorial will be coming soon for community feedback.

Let’s shape these up so newcomers can quickly get up and running and minimise confusion around adopting OCaml.

Thanks for your help!

New project, old technique: DkSDK FFI OCaml

jbeckford announced

Problem: Let’s say you want to write code in an obscure, rarely breaks top 50 popularity programming language. Your compiled code must run in diverse runtime environments: Android, iOS, desktop, etc. But you are loathe to throw away the numerous libraries and the vast ecosystem of tools that are in the dominant Java, Swift, and C++ (etc.) environments.

DkSDK FFI is a framework that solves the above problem. One framework component, DkSDK FFI OCaml, is being released now (pending ocaml/opam-repository PR24316), and other framework components like DkSDK FFI Java will be released in the future. Let’s look at some example code written in OCaml, but bear in mind two things:

  1. Each of the two examples below can be written in any DkSDK FFI language.
  2. I’ll explain what is going on after the examples.

Here is an example of registering a DkSDK FFI “COM object” in OCaml. Scroll down to see the full example.

When DkSDK FFI Java is released, this example could be written in Java. When DkSDK FFI Swift is released, this example could be written in Swift. And so on.

#use "topfind";;
#require "DkSDKFFIOCaml_Std";;

open DkSDKFFIOCaml_Std ;;

open ComStandardSchema.Make (ComMessage.C)
open Com.MakeClassBuilder (ComMessage.C) ;;

let com = Com.create_c () ;;

let create_object return args =
    let number = Reader.Si32.(i1_get (of_message args)) in
    return (New
        (Printf.sprintf
        "instance constructed with create_object(args = %ld)"
        number)) ;;

let ask ~self return args =
    let question = Reader.St.(i1_get (of_message args)) in
    let ret =
      Printf.sprintf "I am an %s and I was asked: %s" self question
    in
    let bldr = Builder.St.(let r = init_root () in i1_set r ret; r) in
    return (Capnp bldr) ;;

register com ~classname:"Basic::Question::Taker"
      [
        class_method ~name:"create_object" ~f:create_object ();
        instance_method ~name:"ask" ~f:ask ();
      ] ;;

Here is an example of using that registered DkSDK FFI COM object from OCaml.

When DkSDK FFI Java is released, this example could be written in Java. And so on.

module BasicQuestionTaker = struct
  open ComStandardSchema.Make (ComMessage.C)
  let create com =
      Com.borrow_class_until_finalized com "Basic::Question::Taker"
  let method_create_object = Com.method_id "create_object"
  let method_ask = Com.method_id "ask"

  class questiontaker _clazz inst =
    object
      method ask question =
        let args =
          let open Builder.St in
          let rw = init_root () in i1_set rw question; to_message rw
        in
        let ret_ptr =
            Com.call_instance_method inst method_ask args
        in
        Reader.St.i1_get (Reader.of_pointer ret_ptr)
    end

  let new_questiontaker clazz number =
    let args =
      let open Builder.Si32 in
      let r = init_root () in i1_set_int_exn r number; to_message r
    in
    Com.call_class_constructor
      clazz method_create_object (new questiontaker clazz) args
end ;;

let questiontaker_clazz = BasicQuestionTaker.create com
let questiontaker =
  BasicQuestionTaker.new_questiontaker questiontaker_clazz 37 ;;

let () = print_endline (questiontaker#ask "What am I?") ;;

(* Output:
    I am an instance constructed with create_object(args = 37)
    and I was asked: What am I?
*)

Context: A long time ago in a galaxy far, far away, Microsoft invented the Component Object Model (“COM”) for programming languages like Visual Basic, C and Delphi to interoperate on the same machine. COM was an application binary interface (ABI) where COM “objects” were given C++ style virtual tables; subsequently these COM objects had the functionality of simple C++ objects without needing C++. These COM objects also solved cross-language memory management using manual reference counting. And then Microsoft went crazy trying to expand its reach, and unsuccessfully pushed for a COM enhancement (ActiveX) to be the backbone of the “World Wide Web”. But COM survived in several places like DirectX, Apple Core Foundation, and Mozilla XPCOM.

Context: There is a neat remote procedure call (“RPC”) system called Cap n’ Proto RPC. It features zero overhead for encoding and decoding, bindings to many programming languages, and promise pipelining to solve the distributed, cascading latency problem that inspired GraphQL. Think of Cap n’ Proto as a very fast JSON framework combined (optionally) with remote procedure calls.

A concrete example: You make an Android application using Java in Android Studio, with the business logic (or data layer or “Model” objects) written in an obscure language like OCaml. And an iOS application using Swift in Xcode, re-using the same business logic you already wrote in OCaml. And a desktop application using a C++ GUI framework, re-using the same business logic. Wrapping your OCaml objects as COM objects is one way for object-oriented languages like Java, Swift and C++ to communicate with your OCaml code. But that sounds like a lot of work, and it could be! And I haven’t even mentioned the overhead of calling methods using a C/C++ calling convention from a foreign programming language.

Enter the DkSDK FFI framework: DkSDK FFI combines both COM and Cap n’ Proto for same-process interoperability. We get rid of COM’s C/C++ calling convention. That means there is no stack-allocating each function parameter and encoding/decoding each foreign language type as a C native type. Instead each function call has a single argument … a Cap n’ Proto “Struct” (think of it as a JSON object with little or no encoding overhead) … and a single “Struct” return value. Like COM, DkSDK FFI objects are reference counted. Unlike COM, DkSDK FFI arguments and return values are also reference counted. In other words, DkSDK FFI core concepts are simple, uniform, accessible in many programming languages, and have been shown to work over decades.

Today this announcement is a preview for OCaml-ers. Even though DkSDK FFI can be used, for example, to interoperate between Java and Swift, the OCaml language has slight privileges over other languages.

  • First is in licensing. When DkSDK FFI Java is released in a few months to the predominant “Maven” Java binary package manager, the binding source code and Java .so and .dll shared libraries will be available under an “OSL-3.0” OSI-approved open source license, but only for one OS architecture (probably Linux x86_64 since easy to run with Docker). If you need other OS architectures you can purchase the full source code with a DkSDK license, or get it free on request if you are a security engineer, educator or a related-field academic researcher. And when DkSDK FFI Swift is released next year, it will be OSL-3.0 licensed only for one OS architecture (probably Darwin arm64). DkSDK FFI OCaml? It will be OSL-3.0 licensed so it can be used alongside all other released OSL-3.0 architectures (ex. Linux x86_64, Darwin arm64 and so on).
  • Second, there may be some leaky abstractions in DkSDK FFI that help OCaml. One example is DkSDK FFI method identifiers are 31-bit identifiers.

You’ll need to wait for your foreign programming language (Java, etc.) to be implemented in DkSDK FFI. Reference material and timelines are:

  • DkSDK FFI OCaml - https://diskuv.gitlab.io/distributions/1.0/dksdk-ffi-ocaml/DkSDKFFIOCaml_Std/DkSDKFFIOCaml_Std/index.html. If you browse that odoc documentation, be sure to click on its links to modules. There is a lot of documentation in there, but I haven’t yet organized it narratively.
  • DkSDK FFI C - https://diskuv.com/ffi-c/help/latest/. This is the already-completed kernel of the DkSDK FFI platform. Other language implementations like DkSDK FFI OCaml use it. However, I don’t think it makes sense for an end-user to use it directly: writing COM objects in a language without objects like C is verbose, and the ocaml-ctypes library is mature and relatively easy to use. But the FFI C documentation will help you debug stack traces and generally understand what is going on. And if you want it, full source is available today with a DkSDK license
  • DkSDK FFI C++, Java, Swift - When these are ready for public release I’ll send announcements. Earliest will be Java in a few months.
  • DkSDK FFI Rust, Web (WASM), Python - Since the kernel DkSDK FFI C is C11 standards compliant and is a glorified manipulator of memory buffers, DkSDK FFI should have a straightforward WASM implementation. But I’m not sure if these will get done because I don’t personally need these. If a few DkSDK subscribers need them, I’ll prioritize them.

Practical OCaml

ostera announced

I’ve been writing Practical OCaml for a few weeks, a blog where I’ve been exploring different aspects of OCaml. Here’s some of the content I’ve published so far:

https://practicalocaml.com/how-i-explore-domain-problems-faster-and-cheaply-in-ocaml/

https://practicalocaml.com/a-quick-guide-to-gadts-and-why-you-aint-gonna-need-them/

Just thought that some of you may enjoy this :pray: – I’ve got more in the pipeline, as you can read here.

Hope you like it and feel free to spread the word elsewhere :speaking_head:

Static analysis in Flambda 2 - Talks at the Cambium Seminar

OCamlPro announced

We are delighted to announce that there is a seminar in the Cambium team at Inria today at 11am CEST, Paris, related to Flambda 2. The seminar is accessible online at https://bbb.inria.fr/pot-xb8-cq4-y6w

This talk follows our previous talk where we showed what motivated our work on Flambda 2 with Jane Street, and how we designed it to be maintainable, efficient, powerful, and extensible. We presented some concrete benefits of this design: new optimizations, but also the ability to easily integrate new language features.

All Cambium seminars are announced here: http://cambium.inria.fr/seminar.html

Description of today’s talk:

  • Title: Static analysis in Flambda 2
  • Date: Monday 28th of August, 11 am (Paris)
  • Speakers: Vincent Laviron, Pierre Chambart, OCamlPro
  • Abstract: Following our previous talk on Flambda 2, we will present the analysis used by Flambda 2. It is formalized as an abstract domain, and we will present its major characteristics and features: support for constant propagation and immutable block shapes, as well as relational properties such as aliases and projections, and support for higher-order values through closures and function summaries. We will show how it integrates with the rest of Flambda 2, and in particular how it allows us to optimize various concrete pieces of code.

OCamlPro later added

The talk’s slides have been published on the Cambium seminar page.

Doc Review: Install OCaml and Getting Started

Christine announced

We’re now ready for Community feedback on the Install OCaml tutorial. This one is very important for newcomers. We’d love your help to ensure the Install page is clear, straightforward, and complete for newcomers.

Here is the Install OCaml PR. Looking forward to your feedback!

After that, it would be great if you had time to also review the next two “Getting Started” documents:

  • A Tour of OCaml
  • How to Write an OCaml Program

Other OCaml News

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.