OCaml - Access Derived Functions from Another Module

63 views Asked by At

If a record is defined in a module in lib and it contains a deriving annotation that generates functions, how can those functions be used in another module?

For example, the yaml/ppx_deriving_yaml opam module contains a [@@deriving yaml]. If [@@deriving yaml] is applied to a record, functions are generated, such as {record_name}_to_yaml, which converts a record to a Yaml data structure.

Example: When [@@deriving yaml] is added to the book record, when compiled, there will be several functions generated, one being book_to_yaml.

(* ./lib/books.ml *)
type book = { 
  title: string;
  authors: string list
} [@@deriving yaml]

But if you try and access book_to_yaml from outside the Books module, it is unavailable.

Why is that function unavailable? How is it accessed?

(* ./bin/main.ml *)
let () = 
  let (b: book) = { title = "Cryptonomicon"; authors = [ "Neal Stephenson" ] } in
  Yaml.pp Stdlib.Format.std_formatter (book_to_yaml b);
                                 Error ^^^^^^^^^^^^

My assumption is that this is something specific to how deriving and modules work.

1

There are 1 answers

0
Greg On

This doesn't answer why, but is one way I found around the issue.

Lets assume the library is named 'bookstore':

(* ./lib/dune *)
(library
  (name bookstore)
  (libraries yaml)
  (preprocess
    (pps ppx_deriving_yaml)))

A function can be defined in the module with the record, which directly exposes the generated function. In this case book_to_yaml will be exposed with a function called convert_book_to_yaml.

type book = { 
  title: string;
  authors: string list
} [@@deriving yaml]

let convert_book_to_yaml = book_to_yaml

Now you can access convert_book_to_yaml by either adding open Bookstore.Books or directly with the full namespace Bookstore.Books.convert_book_to_yaml.

(* ./bin/main.ml *)
let () = 
  let (b: Bookstore.Books.book) = { title = "Cryptonomicon"; authors = [ "Neal Stephenson" ] } in
  Yaml.pp Stdlib.Format.std_formatter (Bookstore.Books.convert_book_to_yaml b);