OCaml Weekly News
Hello
Here is the latest OCaml Weekly News, for the week of May 09 to 16, 2023.
Table of Contents
- Rendering React in OCaml
- Ahrefs is Hiring
- tmx: Import 2D game maps with ease
- Brr 0.0.5, the WebGPU edition
- A bestiary of GADT examples?
- Open-source tool to make a static blog in OCaml?
- BER MetaOCaml N114, for OCaml 4.14.1
- Building iOS apps with OCaml?
- A Minimal Prototype of In-Package Search is on staging.ocaml.org
- New release of Fix (20230505)
- QCheck 0.21
- Old CWN
Rendering React in OCaml
David Sancho announced
Here is server-reason-react
, the OCaml implementation of React I have been working on:
https://sancho.dev/blog/server-side-rendering-react-in-ocaml
The blog post is targeted for a Frontend/JS dev, but I believe it can be interesting from the OCaml site as well.
server-reason-react
is an implementation of react-dom/server
and some of React’s internals in OCaml. The purpose is to render HTML markup from the server for a Reason React application natively.
It supports hydration (renderToString) and full render (renderToStaticMarkup) and most unit tests from ReactDOMServer are migrated as well. Basically, to ensure hydration “hacks” work the same way as react’s DOM (in JavaScript).
It’s obviously fast, talking about req/s: x10 against Node and x6 against Bun on the same codebase. Performance is not the priority, though. I did 0 perf work but is cool. If you want to help making it very fast, let me know!
The priority is to implement streaming and later RSC. Can’t wait to try OCaml multicore with Server components.
All of this is thanks to Melange, and I’m grateful to work with @_anmonteiro and @javierwchavarri.
Ahrefs is Hiring
benmonopoli announced
As always here at Ahrefs we’re on the lookout for OCaml devs.
We are headquartered in Singapore but our team is dotted all over the place so we’re open to remote too.
Check out our posting here
Feel free to reach out for more info.
Louis Roché then added
To try to give some context as the job post on the website is pretty dry
Ahrefs is heavily invested in Melange to compile ocaml to javascript. With it the company is also putting resources to maintain the projects related to reasonml. Some recent posts from @jchavarri and @davesnx:
- https://discuss.ocaml.org/t/ahrefs-is-now-built-with-melange/12107
- https://discuss.ocaml.org/t/ann-rendering-react-in-ocaml/12133
A bunch of commonly used libraries that you probably have heard about are maintained by ahrefs or with the help of ahrefs
- https://github.com/ahrefs/atd
- https://github.com/ahrefs/ocaml-sodium
- https://github.com/davesnx/styled-ppx
- https://github.com/ygrek/ocaml-extlib
There’s more at https://github.com/ahrefs
When not maintaining we try to contribute. One example is ocaml-lsp
We are also sponsoring projects:
Conferences:
(also the reasonml conferences in the past)
And last but not least the OCaml Software Foundation https://ocaml-sf.org/
tmx: Import 2D game maps with ease
fishyfriend announced
tmx
is an OCaml library for reading data files from the 2D game map editor
Tiled.
The library aims for broad coverage of Tiled’s TMX file formats. It provides an imperative context for loading TMX data files and a collection of immutable types corresponding to TMX data structures.
tmx
emulates the semantics of TMX data structures as they exist in the Tiled desktop application, including proper application of
custom property inheritance and
object templates. This allows the attributes of game resources in OCaml to match exactly what is observed in the editor.
Check out the project page for more.
Brr 0.0.5, the WebGPU edition
Daniel Bünzli announced
There’s a new release of Brr. Brr is an ISC licenced toolkit for programming browsers with the js_of_ocaml compiler.
The highlight of this release is support for the new
WebGPU API that is gradually being rolled out in browsers. You can find it in the
Brr_webgpu.Gpu
module – the binding is large and has been little tested so far, early adopters may run into glitches. But the
250 lines example to render the usual triangle works.
The release notes have the other changes.
The WebGPU binding work was supported by a grant from the OCaml Software Foundation. A big thank to my donators aswell, I welcome and thank a new private donator.
- Homepage: https://erratique.ch/software/brr
- Docs: https://erratique.ch/software/brr/doc (or
odig doc brr
) - Install:
opam install brr
(once this PR has been merged)
A bestiary of GADT examples?
Chet Murthy asked
Is there someplace a bestiary of GADT examples ? I’d like to find such a thing in order to more-fully understand the universe of possibilities for using GADTs in programming. I’ve never used ’em, and while, sure, reading about the theory is great, and reading a few example is cool, it would be complementary to have a bottom-up understanding (lots of examples) as well as a top-down one.
Yawar Amin replied
We do seem to have a home-grown ’GADT’-iary: https://discuss.ocaml.org/t/open-source-projects-using-gadts/9640
A couple of new and interesting ones since that thread:
- https://discuss.ocaml.org/t/ann-petrol-1-0-0-a-high-level-typed-sql-api-for-ocaml-designed-to-go-fast/11166
- https://github.com/yawaramin/ocaml_sql_query/blob/0516ea6c7d80a6fcf61c4d9ba551b9f0b780d9ff/lib/sql.ml#L21 by yours truly to model ’a query can return either nothing or some resultset’
Kiran Gopinathan also replied
I haven’t got round to properly publicising it, but I actually wrote blog post about the internal development process of Petrol, and how I gradually moved from Caqti, to macros, to GADTs which may be useful:
Armael also replied
Not exactly examples of GADTs “in the wild”, but I’ve found @yallop ’s slides (from the Advanced Functional Programming course at Cambridge) to be interesting for seeing “GADT design patterns”: https://www.cl.cam.ac.uk/teaching/1617/L28/lecture-8-slides.pdf , https://www.cl.cam.ac.uk/teaching/1617/L28/lecture-9a-slides.pdf. (I hope it is OK to link those here!)
Gaëtan Gilbert also replied
We use a lot of GADTs in Coq For instance https://github.com/coq/coq/blob/14946eb0cbce09c1a63d36aac21ccb1161fbd869/plugins/ltac2/tac2ffi.ml#L16-L18 used to have arbitrary-arity functions Slightly simplified:
type ('arg,'result,'f) arity = | One : ('arg, 'result, 'arg -> 'result) arity | More : ('arg, 'result, 'f) arity -> ('arg, 'result, 'arg -> 'f) arity type ('arg, 'result) nary = Nary : ('arg, 'result, 'f) arity * 'f -> ('arg, 'result) nary type value = | Closure of (value, value) nary | SomeInt of int let to_nary = function | Closure f -> f | SomeInt _ -> failwith "can't apply someint" let rec apply : type f. (value,value,f) arity -> f -> value list -> value = fun arity f args -> match args, arity with | [], _ -> Closure (Nary (arity, f)) | [arg], One -> f arg | arg :: args, More arity -> apply arity (f arg) args | arg :: args, One -> let f = f arg in let Nary (arity, f) = to_nary f in apply arity f args let apply_val f args = let Nary (arity, f) = to_nary f in apply arity f args let addf x y = match x, y with | SomeInt x, SomeInt y -> SomeInt (x + y) | _ -> failwith "addf got non-ints" let addval = Closure (Nary (More One, addf)) let addval' = Closure (Nary (One, fun x -> Closure (Nary (One, fun y -> addf x y)))) let () = assert (apply_val addval [SomeInt 1; SomeInt 2] = apply_val addval' [SomeInt 1; SomeInt 2]) let () = assert (apply_val addval [SomeInt 1; SomeInt 2] = SomeInt 3)
Or https://github.com/coq/coq/blob/14946eb0cbce09c1a63d36aac21ccb1161fbd869/engine/evd.ml#L208-L230 a record where some fields are nontrivial if and only if some other field is nontrivial
or around https://github.com/coq/coq/blob/14946eb0cbce09c1a63d36aac21ccb1161fbd869/gramlib/grammar.ml#L201 which replaced some Obj.magic in the camlp5 engine this file is derived from.
I guess you can find more by looking at https://github.com/search?q=repo%3Acoq%2Fcoq+GADT&type=commits
Anton Bachin also replied
'a Lwt.t
promise states and several other types in Lwt are internally GADTs. See
https://github.com/ocsigen/lwt/blob/cc05e2bda6c34126a3fd8d150ee7cddb3b8a440b/src/core/lwt.ml#L321-L340. This is mainly to use the existential types capability of GADTs.
Calascibetta Romain also replied
You can also check a protocol implementation with GADT here (which proves that a client should never send something to another client): https://github.com/dinosaure/bob/blob/main/lib/state.ml. A detailled article is available here: https://blog.osau.re/articles/gadt_and_state_machine.html
Also, I re-implemented a printf
function with a
promotion mechanism of certains values (à la C) here:
https://github.com/mirage/conan/blob/main/src/fmt.ml. You can also check the implementation of the decision tree which helps us to regognize MIME type, it’s a GADT too:
https://github.com/mirage/conan/blob/main/src/tree.ml#L10.
Finally, you can check this typed lambda calculus: https://github.com/mirage/mirage-lambda/blob/a89b265b552f8b63ff725fc942f41a276fabb4f5/src/typedtree.ml#L436 and the transformation from a simple lambda-calculus with a typed one (and where we prove that variables are bounds via the De-Bruijn indice).
EDIT: Ah and probably the most complicated GADT I ever see which has a real application, a zipper on an AST where the path is a GADT.
Emile Trotignon also replied
Menhir generates code with gadts using the method described in this paper
In that case, the specific technique used is ADTs without allocation, of which a more simple example is the following :
type 'a number = | Float : float number | Int : int number let show_number : type n. n number -> n -> string = fun witness n -> match witness with | Float -> string_of_float n | Int -> string_of_int n
zapashcanon also replied
In owi, to allow the user to define host functions usable from Wasm, we also use GADTs.
Jean Christophe Filliatre also replied
Arthur Wendling (Tarides) has an implementation of Kaplan/Tarjan 99 (Purely Functional, Real-Time Deques with Catenation), which makes a non-trivial use of OCaml’s GADT. See https://github.com/art-w/deque
Open-source tool to make a static blog in OCaml?
deep in this thread, roddy said
My tool finch meets most of these requirements. I think it is much more Hugo/Jekyll-like than YOCaml or Soupault. It should be easy for you to add any features you need, it’s <600 lines of straightforward OCaml.
Two examples of its use are its documentation and my meagre website.
BER MetaOCaml N114, for OCaml 4.14.1
Oleg announced
BER MetaOCaml N114 is a strict superset of OCaml 4.14.1 for ``writing programs that generate programs’’. BER MetaOCaml adds to OCaml the type of code values (denoting ``program code’’, or future-stage computations), and two basic constructs to build them: quoting and splicing. The generated code can be printed, stored in a file – or compiled and linked-back to the running program, thus implementing run-time code optimization. A subset of the generated OCaml code can also be converted to C, via offshoring. (The generated C needs no particular runtime or GC.) A well-typed BER MetaOCaml program generates only well-scoped and well-typed programs: The generated code shall compile without type errors. Staging-annotation–free BER MetaOCaml is identical to OCaml; BER MetaOCaml can link to any OCaml-compiled library (and vice versa).
The main changes in version N114 are
- smoothing the path for the possible future integration into OCaml;
- starting and almost finishing the complete solution to the long-standing CSP problem;
- complete support for offshoring
The problems of syntax are said to command the most discussion. This message is no exception. In MetaOCaml, code to be generated is enclosed in brackets: .<1 + 2>. (which may contain `holes’, to be filled with code: fun h -> .<1 + .~h>. where .~, analogous to unquotation in Lisp, is called escape). Although `.<’ and `.~’ are not valid in OCaml and hence can’t be confused, `>.’ is a a valid OCaml operator (and so are the operators that start with that character sequence, like `>..’ and `>.>.’). In fact, there are some libraries that do define the operator `>.’ and which therefore cannot be used in MetaOCaml code. Version N114 introduces an adaptive lexer, which treats `>.’ identically to ordinary OCaml, until it sees the first `.<’. If one arranges the code such that all occurrences of the operator `>.’ come before the opening bracket, one can use the operator even in the same file as brackets. If one cannot arrange code such way, or must use `>.’ within brackets, one has to use the alternative syntax for brackets and escapes:
fun h -> [%metaocaml.bracket 1 >. [%metaocaml.escape h]]
although one may prefer
fun h -> [%metaocaml.bracket 1 >. .~h]
For more explanations, please see https://okmij.org/ftp/ML/MetaOCaml.html particularly about CSP, and https://okmij.org/ftp/meta-programming/tutorial/genc.html about offshoring. See also ChangeLog and NOTES.txt in the BER MetaOCaml distribution.
BER MetaOCaml N114 should be available through OPAM, hopefully soon. In the meanwhile, it is available as a set of patches to the OCaml 4.14.1 distribution.
https://okmij.org/ftp/ML/ber-metaocaml.tar.gz
See the INSTALL document in that archive. You need the source distribution of OCaml 4.14.1.
Building iOS apps with OCaml?
RobertN asked
Is it possible to create iOS apps with OCaml? I know it might take some extra work to use a foreign-function interface to call Objective-C functions to create the UI objects. But I’m wondering if I can cross compile for ARM and send a binary to my iPhone, and eventually the App Store. I’ll be working from macOS (x86).
I’m also interested in macOS apps for the App Store, which probably require cross-compiling to make an ARM+x86 binary of some kind.
Daniel Bünzli replied
Don’t know what the state of that is but at least it has been done at some point.
Nathan Fallet also replied
I’ve already seen people trying to do that. Here is an example.
It’s not from me but it’s an example I got shown when I built my OCaml editor for iOS/iPadOS/macOS.
jbeckford added
Couple more options …
Option 1: I mentioned last week in an unrelated thread that there is an opam package `dkml-base-compiler` that does cross-compilation. It supports most of the Android cross-compile matrix (ex. x86 -> arm32), and the macOS (ex. x86_64 -> arm64). I haven’t updated the official opam package to do iOS cross-compiles b/c most of my open-source time commitment has been for Windows. If you know how to compile the OCaml compiler, please extend that package! The bits will be very similar to the macOS cross-compiler, and I can guide you. See: https://discuss.ocaml.org/t/how-to-compile-ocaml-program-on-linux-for-running-on-freebsd/12110/4?u=jbeckford
Option 2: If you want a more out-of-the-box solution, you can use my commercial DkSDK native development kit. From an OCaml perspective, it is a OCaml-beginner friendly kit that embeds OCaml into other languages and frameworks. Two short-term things are relevant. 1) The docs mentions C a lot, but only because I haven’t finished writing its FFI. It will support OCaml objects <–> Objective-C/Swift objects using Apple’s Foundation library. 2) I inadvertently broke support for Xcode builds, but that will get fixed sooner or later (depending on the interest).
Anyway, ping me privately if Objective-C/Swift dev in Xcode with the Run button automatically building FFI-supported OCaml code sounds like a fit.
Vincent Balat also replied
Be Sport app is written in OCaml (iOS, Android, Web client and server) with Ocsigen (Eliom, Js_of_ocaml, Ocsigen Start…) as an HTML5 app (with Cordova) https://apps.apple.com/fr/app/be-sport/id1104216922
A Minimal Prototype of In-Package Search is on staging.ocaml.org
Archive: https://discuss.ocaml.org/t/a-minimal-prototype-of-in-package-search-is-on-staging-ocaml-org/12163/1
Sabine Schmaltz announced
We added an experimental, incomplete and basic in-package search to staging.ocaml.org. :camel: The current prototype implementation uses an existing JavaScript library. That turned out to be the quickest / least-effort way to get something up and running while we work behind the scenes on something more refined.
On https://staging.ocaml.org/p/dream/latest (or any other package for which documentation has been successfully built by the documentation pipeline) you should see a search bar that allows you to search identifiers within the package.
The goal from our side is to bring a “minimum useful product” to you quickly. Please let us know if there are any problems or wishes for a “version 1.0.0” of the search.
If no show-stopping issues are uncovered, we’ll go ahead and apply a patch to the live site at ocaml.org by end of the week or early next week. :slight_smile:
Thank you @panglesd, @EmileTrotignon, and @art-w for enabling this! I spent surprisingly little time on the integration into staging.ocaml.org so far, so it’s going to be fun to see where this goes.
Barisere Jonathan asked and Sabine Schmaltz replied
Sid Kshatriya then added
To suplement to what @sabine mentioned, I would like to recommend odig
.
odig
is a very easy way to invoke odoc
on your local machine. See
https://erratique.ch/software/odig
New release of Fix (20230505)
François Pottier announced
Frédéric Bour and I are pleased to announce a new release of Fix.
In short, Fix is a toolkit that helps perform memoization and fixed point computations (including data flow analyses). More generally, it offers a number of basic algorithmic building blocks that can be useful in many circumstances.
In this release, two new modules have been added:
- Fix.Minimize offers a minimization algorithm for deterministic finite automata (DFAs). It is based on Antti Valmari’s 2012 paper, “Fast brief practical DFA minimization”.
- Fix.Partition offers a partition refinement data structure, which is used by the minimization algorithm, and could be useful in other algorithms.
There are other minor changes.
The library can be installed as follows:
opam update opam install fix.20230505
Documentation is available online.
QCheck 0.21
Jan Midtgaard announced
I’m happy to announce the release of QCheck 0.21, a property-based testing library in the style of Haskell’s QuickCheck :tada: More information is available in the QCheck Github repository and in the package documentation.
The 0.21 release offers better negative test integration and furthermore fixes a couple of bugs in
QCheck.Shrink
and in ppx_deriving_qcheck
:
- make
Test.check_result
,Test.check_cell_exn
, andTest.check_exn
honor test polarity by raisingTest_unexpected_success
when a negative test (expected to have a counter example), unexpectedly succeeds. - fix issue with
ppx_deriving_qcheck
deriving a generator with unboundgen
for recursive types #269 and a related issue when deriving a generator for a record type - fix #241 causing
QCheck.Shrink.int*
to emit duplicates, also affectingQCheck.Shrink.{char,string}
- fix a cornercase where
Shrink.list_spine
would emit duplicates
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.