2

ocaml-inotifyパッケージを使用しようとしています。この質問に関連する部分は、次のように定義できます。

module Inotify : sig
  type wd
  val int_of_wd : wd -> int
end = struct
  type wd = int
  let int_of_wd wd = wd
end

この作業は setuid スクリプトで行われており、inotify の部分を非特権で処理したいので、fork して子の非特権ユーザーに setuid します。ただし、これは、パイプを介して wd エンティティを親に戻す必要があることを意味するため、それらをシリアル化および逆シリアル化する必要があり、int_to_wd関数が必要です。

次のようにモジュールを拡張しようとしました:

module Rich_Inotify : sig 
  include module type of Inotify with type wd := int
  val wd_of_int : int -> wd
end = struct
  include Inotify
  let wd_of_int (wd:int) : wd = wd 
end
module Inotify = Rich_Inotify

ただし、コンパイラはそれwdがであり、intではないことを訴えwdます。これらのタイプが同じであることをどのように説得できますか?

4

1 に答える 1

4

モジュールが実際にこの署名で定義されている場合Inotify、つまり抽象型で封印されている場合、その抽象化を破って int として再定義することはできません。つまり、署名(module type of Foo with wd := int)は巧妙で、必要なインターフェイスを記述していますが、実装はそれを満たしてFooいませ。型チェッカーがそれを許可した場合、型の抽象化はまったくありません。

ocaml-inotifyメンテナーにマーシャリング プリミティブを追加するように依頼する必要があります (必要に応じてローカルでフォークすることもできます)。という事実を公開する代わりに、(将来の実装の変更でもこれらの関数を実装できるように)wd = intとの間で変換関数を公開するか、マーシャリングのみに関心があり、内部の公開を減らしたい場合は、直接 との間で公開することができます。詳細。intstring

プライベート型の略語を使用する、抽象型への変換を行ったり来たりする内部の詳細を公開するソリューションがあります。

sig
  type t = private int
  val mk : int -> t
end

この署名は、内部表現がであることを明らかにし、 orを使用して明示的にintfrom にキャストすることを許可します (これは実行時にノーオペレーションであることを知っています) 。これが有効な記述子であることを確認するために、何らかの範囲チェックを行うと思います。tint(foo :> int)(foo : t :> int)mk

(回避策として、名前を付けてはならない安全でないキャストを使用して、言語の型の安全性を破ることを提案する人もいるでしょう。そうしないでください。これは悪いアドバイスです。)

于 2013-03-07T14:55:31.657 に答える