2011-01-10 4 views
2

私のモジュールのいくつかには、private_methodpublic_methodという2つのメソッドを持つ特定のクラスタイプを実装するグローバルクラスインスタンスが含まれています。モジュールシグネチャ内のクラスインスタンス型の強制

MyModule.my_instance # public_methodは私のプログラムのどこからでも入手できますし、MyModule.my_instance # private_methodMyModuleの中でのみ利用できるようにします。

私は次のことを試みた:

class type public_type = object 
    method public_method : int 
end ;; 

class type private_type = object 
    method public_method : int 
    method private_method : int 
end ;; 

let make_private : unit -> private_type = fun() -> object 
    method public_method = 0 
    method private_method = 0 
end ;; 

module type MY_MODULE = sig 
    val my_instance : public_type 
end 

module MyModule : MY_MODULE = struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end 

しかし、これはエラーになります:

Values do not match:

val my_instance : private_type

is not included in

val my_instance : public_type

私は手動で強制を書くことができます:

module MyModule : MY_MODULE = struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 

    let my_instance = (my_instance :> public_type) 
end 

しかし、私をむしろ単純なものとしてコードサイズを倍にしないでくださいこれ

なぜこのようなことが起こり、どのように対処できるかについてご意見はありますか?

答えて

3

ocamlに暗黙の強制変換はありません。多分それは(あなたがこれらの同じプロパティを持ついくつかのモジュールを持っている場合)ファンクターに強制を置く価値がある:

module Hide(M:sig val my_instance : private_type end) : MY_MODULE = 
struct 
    let my_instance = (M.my_instance :> public_type) 
end 

module MyModule = Hide (struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end) 
+0

これは、明示的なオブジェクト型の式で使用することができます... –

+0

manual(6.11.1)は、 '式(module-expr:module-type)はmodule-exprの型がmodule-typeのサブタイプであることをチェックしますが'私はそれが期待される行動だと思います。 IIRC 3.12ではモジュールを ':>'と強制することは可能です – ygrek

+0

私は恐れています3.12少なくとも変更ログには記載されていませんが、これは不可能です。しかし、**これはなぜ実装されなかったのですか?**彼らがこれをした場合、または彼らがそれについて考えるのではないとタイプシステムに実際の問題がありますか? –

3

おそらくこれを解決するための最良の手法はGarrigueの(「プライベート行タイプで説明したようprivate row typesを使用することです:抽象化無名;私はそれに2番目のリンクを投稿することはできませんので、それを見てください)。 (あなたが必要とするものである)

module type MY_MODULE2 = sig 
    type t = private < public_method : int; ..> 
    val my_instance : t 
end ;; 

module MyModule2 : MY_MODULE2 = struct 
    type t = private_type 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end ;; 

またはオブジェクトパスを持つ::私は一種のMY_MODULEに明示的に強制変換MyModuleというのように行動することを期待

module type MY_MODULE3 = sig 
    type t = private #public_type 
    val my_instance : t 
end ;; 

module MyModule3 : MY_MODULE3 = struct 
    type t = private_type 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end ;; 
関連する問題