7

OCaml で一般的なタイマー関数を実装しようとしています。これは、入力として任意のアリティの関数を受け取り、型'rを返し、次の関数を返します。

  • 同じアリティと入力パラメータのタイプ、および
  • float * 'rフロートが関数で費やされた時間のメトリックとなる戻り値の型(たとえば、によって報告されSys.time()ます)

問題は、任意のアリティの関数を処理できるように実装できないことです。たとえば、次のコード:

タイマーを f =              
   timerf xy = とする                                 
      let t0 = Sys.time ()                                         
      in let 結果 = fxy                                                 
      in let diff = Sys.time() -. t0                                     
      in diff、結果                                    
   タイマーで    

入力アリティ 2 の関数でのみ動作します。任意のアリティの関数を処理するために一般化する方法は明らかではありません。部分関数アプリケーションが魔法のように難問を解決してくれることを期待していましたが、うまくいきません。

4

2 に答える 2

9

任意のアリティでタイマー関数を作成する意図は理解しています。しかし、OCaml では簡単にそれを行うことはできません。

さらに、実際に使用するには、パラメーターが 1 つだけのタイマー関数で十分です。

let timer f x =
   let t0 = Sys.time()                                         
   in let result = f x                                              
   in let diff = Sys.time() -. t0                                     
   in diff, result

g任意のアリティを持つ任意の関数は、次の方法でtimer簡単に渡すことができるため:

let diff, result = timer (fun () -> g x1 x2 x3 ... xN) ()

または部分的なアプリケーションを使用することでより良くなります(@Andreasによって提案されているように):

let diff, result = timer (g x1 x2 x3 ... xN-1) xN
于 2012-04-04T22:01:26.340 に答える
7

コメントに収まらないほど冗長だったパッドのソリューションに関する発言。

実際には、遅延引数の代わりに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

パッドのデザインは、より一般的であるため、最初はより魅力的であり、代わりに次のように書くことをお勧めします:

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

事前に渡されたパラメーターを使用してクロージャーを強制することにより、ここで「存在型」を無料で取得できます。最後の関数引数の型は、timerアプリケーションの型には表示されません。これは実際にはより良いことがわかりました。

もちろん、完全な呼び出しを遅らせて()、パッドの設計で引数として使用することもできます。しかし、私はこれを強制する選択を好みます。そうしないと、そうしないように誘惑されすぎて、後で支払うからです。

于 2012-04-05T13:21:27.043 に答える