Domanda

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

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

While adding open Tree in "main.ml" will solve the problem, it might be preferable to write the following to avoid polluting "main.ml" with eventual irrelevant definitions from "Tree.mli":

let rec size tree = match tree with
  | Tree.Leaf k -> 0
  | Tree.Node (t1,t2) -> 1 + size t1 + size t2
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top