使用带有可选参数的打印机键入格式

问题描述 投票:2回答:1

我正面临着OCaml typer的有趣行为。 typer似乎无法接受带有可选参数的打印机。

当函数具有可选参数时,可以将其键入为不带可选参数的函数。

(** Simple example *)
let (f1 : ?arg : int -> unit -> int) =
  fun ?(arg = 3) () : int -> arg + 5

let f2  : ((unit -> int) -> int) =
  fun f -> f ()

let x : int = f2 f1
(* The type of f1 matches the signature of f2 :
   the optional argument is well discarded. *)

在这里,f1有一个可选参数,但f2 f1输入很好。那是因为(或者至少,这是我所理解的)f2论证的签名包含了f1的类型。可选参数被简单地丢弃。

但是,此行为在打印机中被拒绝,如此示例所示。

 (* Data structure *)
type 'a elt = {
  data : int;
  annot : 'a
}

(* Type of printer annotations *)
type 'annot printer = Format.formatter -> 'annot -> unit

(* Default printer prints nothing *)
let (default : 'a printer) = fun fmt _ -> Format.fprintf fmt ""

(* Generic printer for elts *)
let elt_printer
    ?(print_annot : 'a printer = default)
    (fmt : Format.formatter)
    (elt : 'a elt) =
  Format.fprintf fmt "%i(%a)"
    elt.data
    print_annot elt.annot

(* I don't care about printing the annotation *)
let f (elt : _ elt) =
  Format.printf
    "%a"
    elt_printer elt

这是编译器为在elt_printer调用中使用fprintf̀而返回的内容:

This expression has type
         ?print_annot:'a printer -> Format.formatter -> 'a elt -> unit
       but an expression was expected of type Format.formatter -> 'b -> unit

我相信typer设法推断出'b = 'a elt,但却没有放弃可选参数。

关于这种行为我有两个问题:

  1. 这是第二个例子中typer的预期行为吗?
  2. 如果没有,是否有标准语法禁止使用带有可选参数的函数?例如,有没有办法禁止在第一个例子中使用f1̀作为f2的参数?

先感谢您。

编辑:通过明确其类型强制键入elt_printer没有可选参数。

let f (elt : _ elt) =
  Format.printf
    "%a"
    (elt_printer : _ printer) elt

编辑2:对于带标签的参数,typer严格阻止键入转换,因为必须为参数提供特定名称。这不是我的问题中提出的问题。

types format arguments ocaml optional
1个回答
3
投票
  1. 是的,这是预期的,函数?foo -> bar -> baz不能转换为bar -> baz的函数。它只能在没有foo的情况下应用,这与隐式转换非常不同
  2. 还有解决方案

首先,你可以“不适用”标签:f ?print_annot:None将告知typer print_annot的参数f应被视为缺席。

其次,这是我用于tyxml(see here)的技术,你可以添加一个单位参数:

val pp : 
  ?encode:(string -> string) ->
  ?indent:bool ->
  ?advert:string ->
  unit -> 
  Format.formatter -> doc -> unit

然后用户将拥有如下代码:

let s = Format.asprintf "%a" (Tyxml.Html.pp ()) my_html
© www.soinside.com 2019 - 2024. All rights reserved.