Unbound module Bi_outbuf

That makes sense. But there is still confusion.

jrootham@Doonesbury:~/dev/politics/mchc/murb_model$ dune build
File "lib/project.ml", line 6, characters 7-18:
6 |     |> t_of_yojson
           ^^^^^^^^^^^
Error: Unbound value t_of_yojson
Hint: Did you mean int_of_yojson?

I tried changing the type name to data from t as well, no joy.

Hmmm…

If your project files are as follows:

  • project.mli:
type t =
{
	capital : float
} [@@deriving of_yojson]

val of_file : string -> t

  • project.ml:
open Core

let of_file filename =
    In_channel.read_all filename
    |> Yojson.Safe.from_string 
    |> t_of_yojson
   

Then the issue is that your project.ml file doesn’t contain the definition of type t (interface files in OCaml don’t work like in C/C++). Try updating project.ml as follows:

open Core

type t =
{
	capital : float
} [@@deriving of_yojson]

let of_file filename =
    In_channel.read_all filename
    |> Yojson.Safe.from_string 
    |> t_of_yojson
   

it’s difficult to debug your case without a complete minimal reproduction. We are seeing parts of your project files and guessing as to what the issue could be. The best option would be to upload a small minimal reproduction project that demonstrates your issue somewhere, perhaps GitHub.

Apologies. However, the last suggestion seems to have solved the issue.

I am now rereading the documentation more carefully.

The implementation is minimal at GitHub - jrootham/murb_model: Monte Carlo model for MURB developments
branch ppx

Thanks for putting up with me.

OK, great! One small suggestion, you don’t need to specify [@@deriving of_yojson] in project.mli. The [@@deriving of_yojson] is only needed when you want to make the t_of_yojson function available. It looks like you don’t need to expose it in the interface file as you are only using it in the implementation to read the JSON from a file on disk.

As the saying goes, it depends. Essentially what ppx_deriving does is write functions so you don’t have to (like a mechanical monk), but unlike humans it doesn’t really care how much it will write. And some functions are bigger than others (deriving fields generates a lot of functions and if your data structures are larger the functions get larger as well), so it might affect binary size for sure, but essentially only in the same way as it would be affected if you were to write them out by hand.

@jrootham to come back to your original question, Bi_outbuf is a module from a library called biniou that Yojson used to depend on and it is the library that atd currently generates code for. On the other hand Yojson 2.0 dropped biniou and uses the OCaml Buffer module now, so atdgen has to be adapted. What puzzles me though is how you were able to install Yojson 2.0 and atdgen, since they should conflict, I think there is a constraint on the OPAM packages to make sure that packages that use atdgen (from before the linked patch) do not get installed with Yojson 2.0+. So you might have uncovered some kind of edge case.

Atd supports as far as I understand JavaScript and Python as well, but as @yawaramin states, for a truly multilingual experience I would probably use a format that was designed with multi-language interoperability in mind.

I had pretty good experiences with Protobuf, but only ever used the binary version, not one that serializes into JSON. That had the advantage that readers would also for the most part use the spec files to generate valid encoders/decoders instead of hand-writing decoders/encoders (“oh it is just JSON I can parse this by hand” and voila you suddenly have a program that can’t handle some inputs because while hand-writing some parts were left out accidentally).

For an OCaml-first experience I would use one of the deriving plugins. I just wish there was language-support for deriving functionality, like in Haskell or Rust, because PPXes tend to introduce brittleness to code (though it seems with the ppxlib efforts this has become much better over the years).

This thread leads me to think there is a problem with the book “Real World OCaml”, (which is what lead me here), it doesn’t talk about the deriving plugins, just atdgen.

RWO presents a specific way of using OCaml that many people actually don’t use. For example atdgen to me is a quite heavyweight solution for data serialization. In practice I’ve found the Yojson PPX much simpler to use. And if you look at other strongly statically typed languages like Haskell, Rust, and Scala–they are also doing something conceptually similar to that.

I wouldn’t be so strong-worded as @yawaramin - lot’s of the learnings from RWO are exactly how one would write code in 2022 (compare that with early 2000s code like for exacmple calendar) but RWO can’t cover every possible topic. Some topics may be more or less relevant to you, but I wouldn’t say that this is an issue of the book, just a choice of the authors.

It is however somewhat surprising, given that Jane Street has developed ppx_yojson_conv. But I am sure there were some sensible reasons why atdgen was picked.