OCaml: как установить симпатичный принтер и использовать его в коде? - PullRequest
0 голосов
/ 29 января 2019

В верхнем уровне и отладчике OCaml можно зарегистрировать симпатичный принтер через install_printer printer-name.Есть ли способ добиться того же, но в коде OCaml?Конкретнее, мне нужно средство ведения журнала, которое не требует явного указания симпатичного принтера для каждого вызова log.То есть что-то вроде:

(* First, user sets a global pretty-printer for a type *) 
let pp_foo : Foo -> string = ...
let () = Logging.register pp_foo
...
(* Then it can be used like that *)
let foo : Foo = ...
let () = Logging.log foo

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Не для того, чтобы противоречить тому, что говорит Октахрон, но на самом деле можно получить какое-то оборудование для захоронения, которое будет таким полиморфным.Это было бы хрупко, и действительно не будет различать [], 0, None, но будет работать довольно хорошо со встроенными типами OCaml.Такая функция может быть найдена в различных библиотеках с различными модификациями, например, библиотеки Extlib и Батареи предоставляют ее под именем dump, вот пример взаимодействия с ней верхнего уровня:

# #use "topfind";;
# #require "extlib";;
# Std.dump;;
- : 'a -> string = <fun>
# Std.dump ["hello"; "world"];;
- : string = "[\"hello\"; \"world\"]"
# Std.dump [];;
- : string = "0"
# Std.dump None;;
- : string = "0"
# Std.dump [|"hello"|];;
- : string = "(\"hello\")"
# module Abstract : sig type t val x : t end = 
   struct type t = string list let x = ["hello, world"] end;;
module Abstract : sig type t val x : t end
# Std.dump Abstract.x;;
- : string = "[\"hello, world\"]"
# 

Имея всю эту мощь в ваших руках, я все равно рекомендую вам использовать ее только для целей отладки.

Наконец, если вам интересно, как работает красивая печать высокого уровня,вот ответ.Фактически, он опирается на среду ввода, доступную для верхнего уровня, которая частично является интерпретатором, а частично компилятором.Эта симпатичная типография все еще довольно хрупкая.

0 голосов
/ 29 января 2019

Это невозможно по двум причинам:

Во-первых, OCaml стирает типы во время выполнения.Следовательно, невозможно различить значение с одним и тем же представлением в памяти.Например, [], 0 или None имеют, например, такое же представление после компиляции.

Во-вторых, тип вашей функции log будет 'a. 'a -> unit.Другими словами, в спецификации сказано, что ваш журнал функций должен работать с любыми типами прошлого, настоящего и будущего.Это возможно только в том случае, если ваша функция просто игнорирует свой аргумент, например:

let f _x = g ()

Другими словами, истинный вопрос может заключаться в том, в чем ваша проблема с

let () = Logging.log pp_foo foo

?

...