ocaml - 带有可选参数的 Printf 错误

标签 ocaml

假设我写这个函数:

let f ?(x=0) fmt y = Format.fprintf fmt "%d" (x+y)

其类型为:?x:int -> Format.formatter -> int -> unit

我可以通过指定 x 来调用它或不。

现在,我们这样调用它:

let () = Format.printf "%a@." f 0

我有这个错误:

Error: This expression has type ?x:int -> Format.formatter -> int -> unit
       but an expression was expected of type Format.formatter -> 'a -> unit

好吧,我不明白为什么这会成为一个问题。这个参数是可选的,如果我不放它应该没问题,不是吗? (写 Format.printf "%a" (f ~x:0) 0 显然可以,但是有可选参数有什么意义?)

我的意思是,如果我像这样声明我的函数:

let f ?(x=0) () fmt y = Format.fprintf fmt "%d" (x+y)

其类型为:?x:int -> () -> Format.formatter -> int -> unit并调用Format.printf "%a@." (f ()) 0将工作。所以我猜想存在一个问题,可选参数不能成为函数的最后一个参数,但事实并非如此。

最佳答案

此问题源于非常灵活的 printf 类型:('a, Format.formatter, unit) 格式 -> 'a。当类型检查器推断出 f 的预期类型是 Format.formatter -> int -> unit 时,应用可选参数已经太晚了。在这种情况下,即使稍微帮助类型检查器也可以解决问题(但会破坏原则)

let pf fmt f = Format.printf fmt f
let () = pf "%a@." f 0 (* works *)

请注意,这是一个相当普遍的问题,高阶函数在处理带有标签或可选参数的函数参数时存在一些困难。

关于ocaml - 带有可选参数的 Printf 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49427112/

相关文章:

ocaml - ocamllex 正则表达式的外部定义

OCaml:从列表中删除重复项,同时保持右侧的顺序

algorithm - 使 ocaml 列表中的元素指向新值

f# - 有人拥有或知道 F# 中可用的持久前缀特里树吗?

OCaml "else"语法错误

ocaml - 使用 ocaml utop 打印历史列表

stream - 如何使用 Stream.iter 在 OCaml 中处理来自标准输入的行

ocaml - 可选择将额外数据附加到类型

ocaml - OCaml 可以检查尾递归吗

linker - 包括使用 dune 的子包(没有为模块提供实现,但模块位于 dune 文件中)