I try to use parameterized types in OCaml but it doesnt't work :(
In a first file "tree.ml" I define the type :
type 'a tree =
| Node of ('a tree)*('a tree)
| Leaf of 'a
In another file "intTree.ml", I use this type to define a type t :
open Tree
type t = int tree
Finally, I want to use the type t in a function "size" in "main.ml" :
open IntTree
type r = IntTree.t
let rec size tree = match tree with
| Leaf k -> 0
| Node (t1,t2) -> 1 + size t1 + size t2
When I try to compile these files, I obtain the following error :
File "main.ml", line 6, characters 4-8:
Error: Unbound constructor Leaf
If i defined "main.mli", it doesn't change anything :
type r
val size : r -> int
If I put :
let rec size (tree : r) = match tree with
| Leaf k -> 0
| Node (t1,t2) -> 1 + size t1 + size t2
i have :
Warning 40: Leaf was selected from type Tree.tree.
It is not visible in the current scope, and will not
be selected if the type becomes unknown.
...
I know they are solutions to solve this error quickly (for example, putting "open Tree type t = int tree" in main.ml instead of "open IntTree type t = IntTree.t") but I need to use the previous structure (for other reasons...). Is there a solution ?
Thank you
Every function in OCaml takes exactly one value and returns exactly one result. For instance, our squareRoot function takes one float value and returns one float value. The advantage of always taking one argument and returning one result is that the language is extremely uniform.
Variant types are one of the most useful features of OCaml and also one of the most unusual. They let you represent data that may take on multiple different forms, where each form is marked by an explicit tag.
Pattern matching comes up in several places in OCaml: as a powerful control structure combining a multi-armed conditional, unification, data destructuring and variable binding; as a shortcut way of defining functions by case analysis; and as a way of handling exceptions.
You need to open Tree
in main.ml. You don't need to copy and paste type declaration. In you code compiler tries to guess what is on your mind. That's why adding type annotation manually partially solves the problem.
Compiler sees that you expect tree
to be of type r
, it looks at type r
from module IntTree
(which is opened by you) and there it understands that probably we have this constructors in Tree
module. It opens it with a warning. This feature was introduced rather recently, so don't be suprized that you are not aware of it.
Another solution is to change this:
open Tree
to this:
include Tree
in intTree.ml
. The idea is that intTree
then becomes self-contained by including all the definitions from Tree
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With