5

2つのモジュールがあります。1つはバリアントタイプを定義します。

module A = struct
  type foo = Bar of material | Baz | Boo

  (* other stuff *)
end

fooのバリアントをコンストラクターとしても、別のモジュールの左側としても使用できるようにしたいと思います。

module B = struct
  type foo = A.foo  (* I can abbreviate A.foo by assigning it a local alias *)

  let f (x : foo) = match x with
    | Bar m       -> Bar (g m)  (* Any way to abbreviate Bar and friends? *)
    | Baz   | Boo -> x
end

しかし、 「名前付きオブジェクトの参照」ごとに、バリアント名の前にモジュールパスを付ける必要があります。

  let f (x : foo) = match x with
    | A.Bar m         -> A.Bar (g m)
    | A.Baz   | A.Boo -> x

open他のすべてのものを取得してプルする以外にモジュールパスを使用しないようにスキップする方法はありますAか?

4

2 に答える 2

9

ローカルでAを開くことができます:

let f (x : foo) = A.(match x with
  | Bar m       -> Bar (g m)
  | Baz   | Boo -> x)

また

let f (x : foo) =
  let open A in
  match x with
  | Bar m       -> Bar (g m)
  | Baz   | Boo -> x)

Barサブモジュールで定義して、公開されるものを減らすことができます。

module A = struct
  module BasicDataAndOps = struct
    type foo = Bar of material | Baz | Boo
  end
  open BasicDataAndOps
  (* other stuff *)
end

module B = struct
  open A.BasicDataAndOps
  ...

パターンの外部で使用するために、Bで「スマートコンストラクター」を定義できます。

let bar m = A.Bar m

ETA:Ashish Argwalの答えで説明されているように、型の定義を言い換える可能性を忘れましたtype foo = A.foo = Bar of material | Baz | Boo。例にすでに型の省略形があることを考えると、これが最良の答えです。

タイプベースのラベルの曖昧性解消に関するいくつかの作業が役立つ可能性がありますが、言語に受け入れられない可能性があります。

于 2012-11-24T10:52:26.573 に答える
2

lukstafiが提供した回答に加えて、を定義するときにコンストラクターを言い換えることもできますB.foo

module A = struct
  type foo = Bar | Baz
end

module B = struct
  type foo = A.foo = Bar | Baz

let f (x : foo) = match x with
  | Bar -> "bar"
  | Baz -> "baz"

end
于 2012-11-24T23:25:01.677 に答える