I'm playing with reason, and I wanted to try to do the FFI for debug
in order to learn. I have this code
module Instance = {
type t;
external t : t = "" [@@bs.module];
};
module Debug = {
type t;
external createDebug : string => Instance.t = "debug" [@@bs.module];
};
and I'm trying to use it like this
open Debug;
let instance = Debug.createDebug "app";
instance "Hello World !!!";
but I get the following error
Error: This expression has type Debug.Instance.t
This is not a function; it cannot be applied.
Wasn't instance
supposed to be bind to a function? I also tried with
module Instance = {
type t;
external write : string => unit = "" [@@bs.send];
};
and
open Debug;
let instance = Debug.createDebug "app";
instance.write "Hello World !!!";
but I get
Error: Unbound record field write
What am I missing?
The createDebug
function, according to your declaration, returns a value of type Instance.t
. It is an abstract value, in a sense that nothing is known about its implementation, and you can only use it via its interface. The interface of a type is, basically, all values (functions) that allow you to manipulate a value of this type. In your case, we can find only two such values - the Instance.t
value and Debug.createDebug
function. Both can be used, according to your own declarations, to create such value. No functions are provided to use it.
Probably, you have some misunderstanding of what module is. It is not an object per se, but rather a namespace. It is like a file in file.
Your second example justifies that you're thinking of modules, as they are a sort of runtime objects or records. But, they are just static structures that are used to organize big programs into hierarchical namespaces.
What you're trying to use is actually a record:
type debug = { write : string => unit }
let create_debug service => {
write: fun msg => print_endline (service ^ ": " ^ msg)
}
let debug = create_debug "server"
debug.write "started"
Will yield:
server: started