Types 使用带有可选参数的打印机以格式键入
我正面临OCaml打字机的一个有趣行为。打字机似乎无法接受带有可选参数的打印机Types 使用带有可选参数的打印机以格式键入,types,format,arguments,ocaml,optional,Types,Format,Arguments,Ocaml,Optional,我正面临OCaml打字机的一个有趣行为。打字机似乎无法接受带有可选参数的打印机 (** 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 mat
(** 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. *)
当函数具有可选参数时,可以将其类型化为没有可选参数的函数
(** 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
这是编译器为在fprintf
调用中使用elt_打印机
而返回的内容:
This expression has type
?print_annot:'a printer -> Format.formatter -> 'a elt -> unit
but an expression was expected of type Format.formatter -> 'b -> unit
我相信打字机能够推断出'b='a elt
,但未能放弃可选参数
关于这种行为,我有两个问题:
f1̀
作为f2
的参数elt_打印机
let f (elt : _ elt) =
Format.printf
"%a"
(elt_printer : _ printer) elt
编辑2:
对于带标签的参数,typer严格阻止类型转换,因为必须为参数提供特定的名称。这不是我问题中提出的问题
?foo->bar->baz
不能转换为bar->baz
的函数。它只能在没有foo
的情况下应用,这与隐式转换非常不同f?print\u annot:None
将通知打字机f
的参数print\u annot
应被视为不存在
其次,这是我用于tyxml()的技术,您可以添加一个单元参数:
val pp :
?encode:(string -> string) ->
?indent:bool ->
?advert:string ->
unit ->
Format.formatter -> doc -> unit
然后用户将拥有如下代码:
let s = Format.asprintf "%a" (Tyxml.Html.pp ()) my_html
我的问题的可能重复处理了具有可选参数的高阶函数的类似用法的两种不同行为之间的差异。这个帖子(虽然很有趣)没有提供一个明确的答案。谢谢你的回答,但我不确定你的观点是否理解。在我的第一个示例中,有一个隐式转换。另外,我认为你在第二部分回答了错误的问题。我不想知道如何定义打印机以匹配正确的签名。我想知道如何在一个更简单的示例(参见第一个示例)中应用格式参数中使用的类型限制。