3
votes

From what I understand, module interfaces/signatures are like interfaces in Java. I sort of understand why I get the unbound constructor error, but I'm not sure what to do about it.

I have a trie module and this is part of the trie.mli file:

type ('k, 'v) trie

val empty : ('k, 'v) trie

val is_empty : ('k, 'v) trie -> bool

This is from the test.ml file:

open OUnit

open Trie

let t () =

    assert_equal (is_empty (Trie(None,[]))) true;

    assert_equal (is_empty (Trie(Some 7,[]))) true

This is from the trie.ml file:

type ('k, 'v) trie = Trie of 'v option * (('k * ('k, 'v) trie) list)

The unbound constructor error is coming from the test.ml file. So what I understand is that the interface only provides the abstract module definitions, so I can't use the constructor in the .ml file. So I'm not sure how to go about testing my implementation. Would I just make a new function called create or something?

1
What is the name of constructor that is unbound? Can you provide the full error message? - ivg

1 Answers

4
votes

You can take a look at testing libraries like https://github.com/janestreet/ppx_inline_test and http://batteries.vhugot.com/qtest/ to write your tests inline in the Trie module, where the type is not abstract. Otherwise, yes, you will have to either provide some function(s) for constructing exactly the tries you want, to be used only during testing, or else make the type concrete in the interface. You may also be able to get away with using trie traversal functions to test your tries, instead of constructing example tries manually during testing.

There is also a convoluted approach, in which you give your testing code and the public two different views of the Trie module by defining some module The_real_trie, not constraining it with a signature (such as an mli file), writing your tests against that module, and in trie.ml simply doing include The_real_trie. Trie will then be exactly The_real_trie, but constrained by the signatrue in trie.mli, so with type abstract.