Есть ли способ печати пользовательских типов данных в ocaml?

Я не могу использовать print_endline, потому что для этого требуется строка, и я не думаю (думаю) у меня есть способ конвертировать мои очень простые пользовательские типы данных в строки. Как я могу проверить значения переменных этих типов данных?

Ответ 1

Во многих случаях нетрудно написать собственную процедуру преобразования string_of_. Это простая альтернатива, которая не требует дополнительных библиотек или нестандартных расширений OCaml. Для курсов я преподаю, что использование OCaml, это часто самый простой механизм для студентов.

(Было бы неплохо, если бы была поддержка общего преобразования в строки, но, возможно, материал, получаемый OCaml, будет зависеть.)

Ответ 2

Нет ничего в базовом языке, который сделает это за вас. Существует проект под названием OCaml Deriving (названный в честь функции Haskell), который может автоматически выводить функции печати из объявлений типов. Я не использовал его, но он звучит превосходно.

http://code.google.com/p/deriving/

Как только у вас есть функция для печати вашего типа (производная или нет), вы можете установить его на верхнем уровне ocaml. Это может быть удобно, поскольку встроенная печать на верхнем уровне иногда не делает то, что вы хотите. Для этого используйте директиву #install-printer, описанную в Глава 9 руководства OCaml.

Ответ 3

Существуют сторонние библиотечные функции, такие как dump в OCaml Batteries Included или OCaml Extlib, которые в общем случае преобразуют любое значение в строку, используя всю информацию о времени выполнения, которую он может получить. Но это не сможет восстановить всю информацию; например, имена конструкторов теряются и становятся целыми числами, поэтому они не будут выглядеть точно так, как вы хотите. Вам в основном придется писать свои собственные функции преобразования или использовать какой-то инструмент, который будет их писать для вас.

Ответ 4

В соответствии с предыдущими ответами ppx_sexp является PPX для создания принтеров из определений типов. Вот пример того, как использовать его при использовании jbuilder в качестве вашей системы сборки и используя Base и Stdio в качестве вашего stdlib.

Сначала файл jbuild, который указывает, как выполнить сборку:

(jbuild_version 1)

(executables
 ((names (w))
  (libraries (base stdio))
  (preprocess (pps (ppx_jane ppx_driver.runner)))
  ))

И вот код.

open Base
open Stdio

type t = { a: int; b: float * float }
[@@deriving sexp]

let () =
  let x = { a = 3; b = (4.5,5.6) } in
  [%sexp (x : t)] |> Sexp.to_string_hum |> print_endline

И когда вы запустите его, вы получите этот вывод:

((a 3) (b (4.5 5.6)))

Преобразователи S-выражения присутствуют на всей базе и всех связанных с ними библиотеках (Stdio, Core_kernel, Core, Async, Incremental и т.д.), и поэтому вы можете в значительной степени рассчитывать на возможность сериализации любой структуры данных, с которой вы сталкиваетесь, а также все, что вы сами определяете.