假设我写了这个函数:
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
即可。所以我猜可选参数不能成为函数的最后一个参数,但事实并非如此。
答案 0 :(得分:5)
此问题源于非常灵活的printf
:('a, Format.formatter, unit) format -> 'a
类型。当时,类型检查员推断出f
的预期类型为Format.formatter -> int -> unit
,应用可选参数为时已晚。在这种情况下,甚至可以帮助typechecker解决问题(但打破公国)
let pf fmt f = Format.printf fmt f
let () = pf "%a@." f 0 (* works *)
请注意,这是一个非常普遍的问题,高阶函数在处理带有标记或可选参数的函数参数时会遇到一些困难。