2017-07-11 17 views
0

私は理由で遊んでいます。私はdebugのFFIを学びたいと思っていました。私はこのコードモジュール全体を関数としてバインドする方法は?

module Instance = { 
    type t; 
    external t : t = "" [@@bs.module]; 
}; 

module Debug = { 
    type t; 
    external createDebug : string => Instance.t = "debug" [@@bs.module]; 
}; 

を持っていると私は、この

open Debug;  
let instance = Debug.createDebug "app"; 
instance "Hello World !!!"; 

ようにそれを使用しようとしているが、私は次のエラー

Error: This expression has type Debug.Instance.t 
     This is not a function; it cannot be applied. 

instanceがバインドされることになっていないた取得します機能?私はまた、

module Instance = { 
    type t; 
    external write : string => unit = "" [@@bs.send]; 
}; 

open Debug;  
let instance = Debug.createDebug "app";  
instance.write "Hello World !!!"; 

てみましたが、私は私が何をしないのです

Error: Unbound record field write 

を取得しますか?

+1

は 'Instance.t'は' Instance'モジュールで定義された抽象型であるあなたが使用しようとしている何

は実際にはレコードです。これはモジュールの一種ではありません。モジュールを値として本当に扱いたい場合は、ファーストクラスのモジュール(http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc81)を使用する必要があります。 – camlspotter

答えて

1

createDebug関数は、宣言に従って、タイプInstance.tの値を返します。その実装については何も知られておらず、インタフェースを通じてのみ使用できるという意味で、抽象的な価値です。型のインタフェースは、基本的に、この型の値を操作するためのすべての値(関数)です。あなたのケースでは、そのような2つの値、すなわちInstance.t値とDebug.createDebugの機能だけが見つかります。そのような価値を生み出すために、どちらもあなた自身の宣言に従って使用することができます。使用する機能はありません。

多分、あなたはモジュールが何であるか誤解しているでしょう。これはオブジェクトそのものではなく、むしろ名前空間です。ファイル内のファイルのようなものです。

第2の例では、ランタイムオブジェクトやレコードの一種であるため、モジュールについて考えることを正当化しています。しかし、それは大きなプログラムを階層的な名前空間に編成するために使用される静的な構造に過ぎません。

type debug = { write : string => unit } 

let create_debug service => { 
    write: fun msg => print_endline (service^": "^msg) 
} 

let debug = create_debug "server" 
debug.write "started" 

が得られます:

server: started 
+0

ありがとうございます。しかし、私がこの外部モジュールのように外部モジュールを定義すると、 '.write @'をなぜ呼び出せないのでしょうか? – ThomasThiebaud

+0

'createDebug'はモジュールのインスタンスを作成しないので(Reasonではそのようなことはありません)、' t'型のインスタンスを作成し、 'write'関数は' t'型とは関係ありません。それは 't'ではなく文字列で動作します。私は答えを正しいものにしてくれました。それは正しい方向にあなたを導きます:) – ivg

+0

ありがとう、私はそれを得ると思います。私はそれをもっと読むだろう – ThomasThiebaud

関連する問題