3

私は ocaml タイプを持っています:

type t = A | B |  ...

およびそのタイプに関するものを出力する関数:

let pp_t fmt x = match x with 
  | A -> Format.fprintf fmt "some nice explanations about A"
  | B -> Format.fprintf fmt "some nice explanations about B"
  | ...

すべての説明を出力する関数を作成するにはどうすればよいですか? に相当するもの:

let pp_all_t fmt = 
   Format.fprintf fmt A;
   Format.fprintf fmt B;
   ...

ただし、新しいコンストラクターを追加するのを忘れると、警告が表示されます。t私の問題は、静かで大きく、大きく変化することであるため、その機能を自動的に構築するものがあるとさらに良いでしょう。

型コンストラクターで「反復」する方法を想像できませんが、おそらくトリックがあります...

編集:私が最終的にやったことは:

type t = A | B |  ... | Z
let first_t = A
let next_t = function A -> B | B -> C | ... | Z -> raise Not_found
let pp_all_t fmt = 
  let rec pp x = pp_t fmt x ; try let x = next_t x in pp x with Not_found -> ()
  in pp first_t

そのため、 を更新すると、コンパイラは、 と を更新する必要があり、を変更する必要はないことtを警告します。アドバイスをありがとうございました。pp_tnext_tpp_all_t

4

3 に答える 3

2

複雑で進化する型の問題を解決するには、実際には、値と関連情報のリストを含むファイルからコードを生成する OCaml プログラムを作成することになるでしょう。

ただし、incr_t : t -> ttype の値をインクリメントする関数がtあり、 t の最初と最後の値を固定したままにしておくと、次のように記述できます。

let pp_all_t fmt =
    let rec loop v =
        pp_t fmt v;
        if v < Last_t then loop (incr_t v)
     in
         loop First_t

OCaml で一般的なポリモーフィックを使用することはできません。これはincr_t、コンストラクターが nullary (値を取らない) である型に対してのみ意味があるためです。incr_tただし、任意のタイプに対して独自のコードを作成できます。

この種のことは、Haskell では非常にうまく処理されます。基本的に、定義が明らかな場合、コンパイラはいくつかの関数を作成します。Derivingと呼ばれる OCaml 用の同様のプロジェクトがあります。私はそれを使用したことはありませんが、値を列挙する問題を処理しているようです。

あなたは「トリック」が欲しいと言っているので、OCaml の安全でない部分を使用しても構わない場合 (個人的にincr_t気にします)、次のように記述できます。

let incr_t (v: t) : t =
    (* Please don't use this trick in real code :-) !  See discussion below.
     *)
    if t < Last_t then
        Obj.magic (Obj.magic v + 1)
    else
        failwith "incr_t: argument out of range"

この種のコードは、可能であれば避けるようにしていますが、危険すぎます。たとえば、型tが値を取るコンストラクタを取得すると、意味のない値が生成されます。まさに「事故待ち」です。

于 2012-09-20T13:35:09.933 に答える
1

あなたができる最も簡単なことは、すべてのコンストラクターのリストを定義することです:

let constructors_t = [A; B; ...]

let pp_all_t = List.iter pp_t constructors_t

これはワンライナーで、簡単に行えます。確かに、それは少し冗長です(灰色または暗い魔法は避けます)が、それでも「私がやりたいことをする」/「痛みを伴う副作用がある」比率の観点からはおそらく最良の方法です。

于 2012-09-20T14:24:31.617 に答える
1

そのようなタスクには、何らかの形のメタプログラミングが必要です。たとえば、ジェフリーの答えから生成するための派生を探求することができます。incr_t

同様のタスクのサンプルコードは次のとおりです:https ://stackoverflow.com/a/1781918/118799

于 2012-09-20T13:51:56.857 に答える