Generics OCaml中的通用定时器高阶函数

Generics OCaml中的通用定时器高阶函数,generics,ocaml,Generics,Ocaml,我试图在OCaml中实现一个通用计时器函数,该函数将以任意算术和返回类型'r的函数作为输入,并返回具有以下内容的函数: 输入参数的相同算术性和类型 ,及 返回类型float*'r,其中float将是函数中所用时间的度量(例如,Sys.time()报告) 问题是我不能以这样一种方式实现它,即它可以处理任何类型的函数。例如,以下代码: let timer f = let timerf x y =

我试图在OCaml中实现一个通用计时器函数,该函数将以任意算术和返回类型'r的函数作为输入,并返回具有以下内容的函数:

  • 输入参数的相同算术性和类型 ,及
  • 返回类型
    float*'r
    ,其中float将是函数中所用时间的度量(例如,
    Sys.time()
    报告)
问题是我不能以这样一种方式实现它,即它可以处理任何类型的函数。例如,以下代码:

let timer f = let timerf x y = let t0 = Sys.time () in let result = f x y in let diff = Sys.time() -. t0 in diff, result in timerf 设计时器f= 设timerf x y= 设t0=Sys.time() in-let result=f x y 在let diff=Sys.time()中。t0 在不同的情况下,结果不同 及时
仅适用于输入算术2的函数。对于我来说,如何将它推广到处理任何算术函数是不明显的。我希望部分函数应用程序能以某种方式神奇地解决这个难题,但我无法让它正常工作。

我理解你的意图,即制作任意算术的计时器函数。但在OCaml中,您不能以简单的方式完成这项工作

此外,只有一个参数的计时器功能在实践中已足够使用:

let timer f x =
   let t0 = Sys.time()                                         
   in let result = f x                                              
   in let diff = Sys.time() -. t0                                     
   in diff, result
由于具有任意算术性的任何函数
g
都可以通过以下方式轻松传递到
计时器

let diff, result = timer (fun () -> g x1 x2 x3 ... xN) ()
或更好地使用部分应用程序(如@Andreas所建议):


关于pad解决方案的评论过于冗长,不适合发表评论

实际上,我发现通过传递
()
而不是延迟参数来强制执行
f:unit->'a
是一种更好的设计

let timer f =
  let t0 = Sys.time() in
  let result = f () in
  let t1 = Sys.time() in
  t1 -. t0, result
原因是我经常使用以下模式:

let fun_to_test = match some_configuration with ... in
timer fun_to_test
pad的设计一开始更具吸引力,因为它更具一般性,鼓励您改为:

let fun_to_test, arg = match some_configuration with .... in
timer fun_to_test arg
这个选择的问题是,一开始看起来很好,在添加了一些选项之后,您会遇到一种情况,即要测试的不同函数的参数不属于同一类型。您有一个类型错误。错误代码示例:

通过使用预先传递的参数强制闭包,我可以在这里免费获得“存在类型”:最后一个函数参数的类型不会出现在
timer
应用程序的类型中。我发现这在实践中更好


当然,您也可以延迟整个调用,并在pad的设计中使用
()
作为参数。但我更喜欢一个迫使我这么做的选择,因为否则我太想不这么做了,我以后再付钱。

如果你知道函数在部分应用时没有做任何有趣的事情(像大多数函数一样),那么你甚至不需要抽象。只要调用
定时器(gx1x2…xN-1)xN
@AndreasRossberg:谢谢,我把你的观点纳入了我的答案中。
let fun_to_test, arg = match some_configuration with .... in
timer fun_to_test arg
let fun_to_test, arg =
  if Random.bool ()
  then (foo, 3)
  else (bar, 3.2)
in timer fun_to_test arg