---
# System prepended metadata

title: OCaml RFC meeting

---

# OCaml RFC meeting

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

David suggests looking at non-maintainer PRs first, which suggest the "Modular IO" by Simon Cruanes:
  https://github.com/ocaml/RFCs/pull/19
  
Gabriel: assign reviewers, maybe in the future a shepherd (in charge of ensuring progress).

Leo: not formal academic reviews. We are trying to reach conesnsus, not judge the document.

## Modular IO

discussion: https://github.com/ocaml/RFCs/pull/1
proposal: https://github.com/ocaml/RFCs/pull/19/files

Xavier: the idea is legitimate and it feels somewhat familiar. I would really like to see proposals like this, it could be an external library to begin with. I would like such proposals to be worked out as external libraries before it is considered for inclusion in the stdlib.

Xavier: can you do line-buffered channels? Can you do Gzip? Can you subsume the transports that are used by cryptokit ? You can't answer them from the description, and you can answer them from a prototype implementation.

Damien: I don't think it works with the external library because you cannot interface it with Printf or Format. You want a proof-of-concept rather than an external library.

Xavier: integration in the standard library is not the first thing to do.

Jérémie: for the record, in Lwt there is a very similar API, the IO API of Lwt is extensible like this. I don't know if there are examples of extending it with Gzip.

(Gabriel: in Batteries there is also a similar API. People don't use it in practice because they are not compatible with the standard library type.)

Mark: a different formulation of what Xavier says is, it's not clear why this particular design is the right one. We want to see complex examples of what you can do. Secondly, doesn't this seem like the sort of libraries that want to change a lot? It would be better if it could be outside the stdlib.

Gabriel: but the ability to extend `in_channel` or `out_channel` is a key point of the implementation.

Florian: it's more a question of fleshing out all the examples that are present in the RFC. Compression on the fly, reimplementing Printf using this new channels. We want to see the code that do implement these functions.

Xavier: a prototype library (or existing library) that comes with examples. I would also like to add that, in the document there are design issues that are left open, what do you do with `seek`? (Gabriel: there is some discussion of `seek` in the Github thread.)

Mark: it might be worth saying that there is obviously a lot of libraries and a lot of code that do complicated IO at the moment, not via these methods, and there are potentially new things with algebraic effects in the pipeline.

Leo: we should try to move more of this into the actual RFC, each of us that had a comment.

Jacques: my impression is trying to do is just trying to abstract the low-level API in C to make it accessible from OCaml -- you can replace it with the implementation. It's not difficult to be exhaustive, so the question is not so much whether this way to do it is going to work or not, it might be whether it's useful or not. Not a huge design space, just abstract the implementation.

Jérémie: there are quite a few usecases in the Lwt case, where it's valid to want to replace how the channel performs the reads.

David: it's worth considering the RFC in two parts: you want to change the two types, all the rest is a discussion of what we might want to do in the future.


## Symbols

thread: https://github.com/ocaml/RFCs/pull/13
proposal: https://github.com/ocaml/RFCs/pull/13/files

Mark: this is mainly to try to make it easy to understand the various places inside the compiler where we manipulate names of statically-allocated values. There are different kinds of these, code, data, some of which is proper OCaml value data and some of which is not, there are various conventions, at some stages the names need to be in certain forms (limited character sets, avoiding clashes with other people's names...). Names are generally difficult.

I originally did this to make things easier in the backend side. One interesting example is that it helped me to understand what we do with packing. Some things I had to previously extract from Leo's brain became immediately apparent from the types. It cleans up a lot of mess we introduced when we added Flambda (should have been cleaned up at the time), and it ... (connection lost).

Xavier: the solution feels a little bit overengineered perhaps. I know of only one open bug related to name management in the compiler, packing is not injective. So before the replace strings with this complicated enumerated type with lots of different cases, really I would need to understand the need a little more. I am not sure I would like to work with the interface you outline, which feels very bureaucratic.

Xavier: [meta] what is the party line on packing? At some point JS decided that packing was unusable, and went on to develop module prefixing + module aliases. Here we have 2/3 RFCs from JS that are about packing. What is the party line on packing?

Leo: one thing that isn't replaced by module aliases is using packing with a `.mli`. For things like functor-packs, the downsides of packing are that you depend on all modules in the pack. But if you make a bunch of mutually-recursive modules, or functors, it's just true anyway.

Leo: so packing is bad for just namespaces (where naming should not induce dependency), but to produce things that you *want* to depend on (you build a functor or mutually-recursive modules) it's actually reasonable.

Mark: if we want to make certain symbols properly local or global, there is no way of doing that at the moment.

Mark: maybe we could split in two, there is the middle-end part around Compilenv.

Pierre: if you want to propagate information about the source-level origin of the symbol, you need something like that.

Gabriel: maybe we could start introducing just semi-abstract types that are equivalent to `string`, but distinguish symbols as we use them.

Jérémie: in general having more typeful representations is better.

Mark: another use-case (than Dwarf) was to reduce executable size by ensuring that symbols are correctly marked with their visibility. This RFC makes this work much easier. (This name is being mangled or this is just the direct name of Foo.Bar.Baz, those are now un-confusable things.)

Gabriel: I'm sympathetic to the argument of making evolution and maintenance easier. But then Xavier wants to avoid over-engineering, how do we find a compromise?

Mark: we could start with the middle-end part.

Xavier: for me in the backend, a symbol is a symbol. I would hope that all symbol names in C-- are fixed. I think you can still do some of your global/local symbol stuff just with symbols that have no structure. Starting with the middle-end may be a way to go forward, but I am very anxious about making something that is too complicated. Printing a symbol is important in debugging output, etc. Let's not go overboard. To me this is not the most important problem we have in OCaml today, there are bigger issues in the type-checker.

Gabriel: but then the namespace implementors say this makes their life user, this would be a user-visible change.

Xavier: so let's see the namespace proposal first.

## Functor packs

https://github.com/ocaml/RFCs/pull/11
https://github.com/ocaml/RFCs/pull/11/files

Leo: the old thing that people request for a very long time, -big-functors, a number of modules abstracted as a functor. There is an existing working prototype of this, which precedes the RFC.

First you make it possible to have a toplevel module be a functor, then you extend this ability to packs. You roughly specify functors by having a `.mli` file for the argument, and then a `.mli` and `.ml` file for the body, and then you pass options to the compiler to tell it that you want to build a functor.

In a way the main thing that this is saving is, if you have 8 modules parametrized, you have to deal with the dependencies between them if you want to pack by hand, and this is a pain.

There is also stuff in there about how to present it sensibly in a build system. This is a fairly common request that we get.

(It relies on a slight cleaning-up of the `-pack` code that requires a behavior change, now you have to pass `-for-pack` when you compiled the `.mli` of a packed module.)

Mark: there is a full implementation of this. One example is, this can be used fairly straightforwardly to produce a compiler that has all of the native backends compiled within in. David said this would be useful for cross-compilation.

Jérémie: inside Jane Street we have an experimental version of the compiler (on Jenga?) that supports it.

Xavier: when I started writing Caml Special Light I wanted to use functors everywhere in the backend. It sounds like a good application of the proposed mechanism; there is one twist, but maybe the backend is not very well structure, the `arch.ml` file in each port has a different interface, sometimes it exports more or less stuff, there is no`.mli`.  for these files, maybe it requires a slightly different mechanism.

Mark: I think there were another couple of twists as well.

Gabriel: meta point, if I correctly understand this  RFC has a prototype that is usable in JS's experimental compiler fork. (And so the last one as well.) When there is a prototype implementation, it could be linked in the RFC proposal.

Xavier: when I read the RFC I'm not quite sure that this is completely usable, will I get the functors I want in the end?

Leo: we made it available a couple weeks ago. For the RFC, there is a worked example at the bottom.

Xavier: give the information, how it looks like and how you use it in JS, this would be useful information.

Xavier: how are the dependencies between the arguments (when you have several arguments) handled? What about ordering of module components?

Jérémie: the prototype is limited to a single argument.

## Symbols again?

Mark: what should we do?

Gabriel: look at the middle-end part in isolation, and maybe show how it is used in the other prototypes that depend on it.

## Unboxed types

https://github.com/ocaml/RFCs/pull/14

Summary: Extend unboxed annotation to avoid boxing when possible due to disjoint tags or value sets
Bundle: inlining + disjointness
Would the unboxing visible in the cmt? Probably stored in the cmt.
Work well with Stephen and Leo proposal

Damien: Close to an old feature before Caml light: heavy for the pattern matching compilers, FFI becomes harder to describe. Complexity is probably not a show stopper anymore.

Didier: physical equality, ordering, hashing change

Jacque: How to keep stable FFI with the optimising unboxed annotation?
Jeremy: versioning or fixed deterministic optimization

## Nominal types

https://github.com/ocaml/RFCs/pull/4

Injectivity annotations are included in 4.12
Jacque: When one works with equation on types, it is important to know which equations can be used.
In OCaml, there are little equations that can be used on abstract types.
We can recover a lot of properties by using nominal (Haskell matchable) types.
This will remove some asymetries in the compiler, in particular the in-module abstract type identities.

Leo: Simpler proposal with just external unique names. Is there an example where nominal types are fully needed?

Pierre: There are some example at Nomadic Labs where nominal are more natural

Leo: Nominal types enshrine inequalities of abstract types. Now users need to think about new name.

Jacque: combination of two features that might be split in two: named abstract types and matchability (that doesn't require a name)

Leo: a good example is really needed.

## Fast native toplevel using JIT

Waiting for a prototype.
Maintainability and portability issues.

Xavier: Who will commit to maintain it?

## Purity annotations

https://github.com/ocaml/RFCs/pull/5

Jacque: Going back to SML weak and strong type variables.
Approximation: when the code is clearly completely pure not be limited by the value restriction.
Complicated by first class polymorphism.

Early approximation or exhaustive implementation.
Interactions with effects?

Leo: Effect prototype: no effect => pure
Why did we drop strong/weak variables and switch to the value restriction?

Jacque: This was done due to abstraction concern. Choosing the types as weak or strong at design time leaks too much detail on the implementation.
However, the issue might have been the default choice. In the proposal, weak types are the default, and users can switch to strong types variables when needed. This choice seems to work better.

Didier: bad defaults, and too much details (arbitrary integer-rank weakness).

Leo: is this a subset of the future full solution?

Didier: We should eval the proposal in the context of tracing effect. Which one are longer, which one is better? 
Can the fast solution be subsumed by the full future solution?

## Forward type definition

Leo: a bick hacky, subsumed by the recursive module packs?

Discussion postponed due to lack of Lexifi participants
