Examples of using Base Map

I wasn’t talking about data compatibility here, but rather about the compatibility of Base with the rest of the ecosystem from the user’s perspective. Since the main introduction to OCaml is now RWO via Base/Core, the more incompatibilities a user encounters as he/she meets the rest of the OCaml ecosystem, the harder it’ll be for said user to become comfortable with OCaml. It feels like we’ve taken one step forward with jbuilder becoming the de facto build system, and then one step back with introducing this new break with the rest of the language.

As one potential example, a user coming to OCaml from RWO may be completely unfamiliar with applying functors since they’re essentially unnecessary in the new Base world. I realize that RWO covers them, but they’re not required for daily use in Base and so may be skipped, similar to the chapter on objects.

2 Likes

I don’t think this is true. Using Base in a serious way pretty much requires the use of functors. Indeed, Maps in particular requires the use of Comparable.Make to build the modules that go into the first-class modules.

More generally, I don’t have a clear sense of what incompatibility you’re concerned about here.

y

2 Likes

Good point. To be picky though, you can define the module using only a function (Comparator.make) and first-class modules.

IMO, RWO is now the main gateway into the language (the other one perhaps being ReasonML). I therefore think it’s useful to consider, when modifying Base/Core, whether it’s a good idea to switch paradigm to something that isn’t used by the rest of the community, because that’s the direction new users will follow. In the case of jbuilder, the new paradigm was clearly superior to everything that existed previously. I don’t care if new users aren’t familiar with the intricacies of _tags files, because there’s pretty much no reason to go back to that Jurassic era. In the case of standard libraries, I’m concerned about introducing brand new paradigms. A conceptual compatibility that existed between the standard library and Core/Base has been removed by the switch to first class modules, and I don’t see the standard library following suite because the advantages of this approach aren’t overwhelming. So we’re dealing with a bigger inter-library chasm forming on the main path of new users to the language. I don’t expect Jane Street to change their approach here though – I’m just voicing my concern.

The philosophy behind Base is pretty clear: it’s not attempting to hew close to the stdlib, and really never has. Instead, it’s trying to cut clear, consistent, and useful APIs, and to do so in a way that minimizes the pain points and misfeatures of the language, like polymorphic comparison and hash functions.

People who want to maximize API similarity to the stdlib should likely look elsewhere.

3 Likes

Am I correct in understanding that things work this way in Core 0.10.0?

Yup. The documentation for 0.10 isn’t up yet, so I can’t point you at it, but it should be up in the next few days.

Note that the docs for v0.10 are now up, and that core_kernel’s doc for Map includes some examples: https://ocaml.janestreet.com/ocaml-core/latest/doc/core_kernel/Core_kernel/Map/

1 Like

Much nicer than Map.Make in the standard library!

What are the advantages of this approach, compared to simply storing functions compare and sexp_of_t in a record when creating a map (provided via parameters to Map.empty() etc.)?

compared to simply storing functions compare and sexp_of_t in a record when creating a map (provided via parameters to Map.empty() etc.)

That would most likely make the Map type unsound, especially when using union/diff functions. Base Map/Set nicely avoids that by minting fresh type on creation.

Ah, brilliant! One thing I initially overlooked is that the module is stored as a phantom type statically, which makes everything quite convenient.