Кратчайший вы могли бы уйти с в теории:
frobnicate (function
| 0x01 -> gets , a_record_uuid
| 0x02 -> gets , a_group
...
)
Конечно, вы будете сорваны OCaml, потому что 1 ° нет «указатель на член» строит в Objective Caml, так что вы бы должно написать fun a s -> a.a_record_uuid <- s
вместо a_record_uuid
(по крайней мере) и 2 ° системы типа не полностью поддерживает экзистенциальную квантификацию, так что тип возвращаемого значения функции не может быть ожидаемым:
exists 'a. int -> (unit -> record * 'a) * ('a -> record -> unit)
Я думаю, вы могли бы решить 1 °, имея именованные функции для установки значений в записи, если вам случится, чтобы сделать это достаточно часто:
type complex = { re : int ; im : int }
let re r c = { c with re = r }
let im r c = { c with im = i }
Это немного неортодоксальные, я думаю, но это, как правило, окупается позже, потому что я склонен использовать их в большинстве функциональных ситуаций. Вы могли бы создать эквивалент в императивном стиле, или вы могли бы принять накладные расходы функции (она добавляет только 20 символов).
В или 2 °, она может быть решена путем сокрытия квантор существования в функции:
let t e read write = let c, x = read() in write x e ; `More_record c
Это позволит вам спуститься:
let t = t a in
match
| 0x01 -> t gets a_record_uuid
| 0x02 -> t gets a_title
...
Я не удивлюсь если CamlP4 поддерживает какой-то сахар для функций назначения. В то же время, если вы используете ссылки вместо изменяемых полей, вы можете сократить это вверх (так как ссылки значения первого класса, поля не являются):
let t read reference = let c, x = read() in reference := x ; `More_record c
match
| 0x01 -> t gets a.a_record_uuid
...
Смущающе простой. – mbac32768