Atdgen - .atd for Constructors with more that one argument

Hey everyone,

Given that i want to generate this type,

type constant =
    Pconst_integer of string * char option
  | Pconst_char of int
  | Pconst_string of string * string option
  | Pconst_float of string * char option

What should be in my .atd file? I tried this ,

type constant = [
      Pconst_integer of (string * string option)
    | Pconst_char of int
    | Pconst_string of (string * string option)
    | Pconst_float of (string * string option)
] <ocaml repr="classic">

But then i get this type,

type constant = Person_t.constant = 
    Pconst_integer of (string * string option)
  | Pconst_char of int
  | Pconst_string of (string * string option)
  | Pconst_float of (string * string option)

which is not same as the one i want. It gives me an error when i try to interchangeably use them.
Error message - This variant or record definition does not match that of type. They have different arities.

I believe this is the old issue with syntax for two-argument constructors

A of (int * int option) is a one-argument constructor where the argument is a pair of type int * int option, while A of int * int option is a two-argument constructor; the first argument is int, the second int option. It looks like your .atd file lists one-argument constructors where it should list two-argument constructors.

1 Like

@n4323 If i write my .atd file like this,

type constant = [
      Pconst_integer of string * string option
    | Pconst_char of int
    | Pconst_string of string * string option
    | Pconst_float of string * string option
] <ocaml repr="classic">

I get this error though,

File "./bin/ml/person.atd", line 12, characters 31-32:
Expecting ']'

The error is pointing to first asterik *

hm, then i don’t know. it almost looks like atdgen chokes on constructors with more than one argument? i have no experience with it unfortunately.

Yes seems like that. Can’t find anything in their documentation as well

In the past when I heavily used Atd, I would use the custom wrapper for this. At least for me, my serialization target was JSON I would define my serialization structure in Atd any my types in OCaml when they didn’t match the obvious defaults.

1 Like

Sorry, I just saw this post from two years ago.

You can’t. The OCaml type generated by atdgen with <ocaml repr="classic"> and with the upcoming atdml by default is:

type constant =
    Pconst_integer of (string * char option)
  | Pconst_char of int
  | Pconst_string of (string * string option)
  | Pconst_float of (string * char option)

i.e. each variant takes either zero or one argument as payload.

Classic variants with multiple arguments are not supported because at the time atdgen was created, I considered them a minor performance optimization and polymorphic variants were the default (this was at a time when I thought polymorphic variants were preferable because we didn’t have type-based disambiguation of variant constructors so we couldn’t define multiple types in the same file that would reuse a constructor name).

Now that we have type-based disambiguation of variant constructors and record field names, I find classic variants to be a better choice most of the time. They are the default in atdml. I’m still not sure about the usefulness of supporting variants of multiple arguments or inline records in the context of ATD and JSON serialization. If you or someone else still wants the feature, please explain how it would be helpful to you (performance?) and post a detailed proposal on atd issues so that we can easily implement it.