Reputation: 1496
I am currently building a program in OCaml, and I have following problem: I need two types that contain a value of the other type. Its basically like this (but a little more complicated):
type a = {
x: some_other_type;
next: b
};;
type b =
NoA
| SomeA of a;;
I noticed I could reference types I didn't define before (so this declaration doesn't throw any error), but if I try to use it, it distinguishes two types of b: The one mentioned in the definition for a, and the one I defined.
I know I could do it the ugly way:
type 'b a = {
x: some_other_type;
next: 'b
};;
type b =
NoA
| SomeA of b a;;
But I would like to know if there is any better solution (Although I have to admit that I quite like being directly able to see that b is a recursive type).
Upvotes: 2
Views: 427
Reputation: 35280
First of all, you're wrong in your assumption, that you can reference an undefined type, e.g.,
# type a = {
x: some_other_type;
next: b
};;
Characters 16-31:
x: some_other_type;
^^^^^^^^^^^^^^^
Error: Unbound type constructor some_other_type
So, your some_other_type
is defined. Probably, you defined it some time ago in your top-level session and forgot about it. If I define some_other_type
, then I will get an Unbound type constructor b
error. So, both b
and some_other_type
were defined previously. Every time you define a new type (not an alias) it will create a fresh new type constructor for you, so type a = A;; type a = A
defines two different (incompatible) types. In fact, you can define two types with the same name only in the interactive top-level (as otherwise, you would need to restart the top-level, if you decided to change type definition). The OCaml compiler will not allow you to define two types with the same name in the same structure.
To solve your problem, you can either use recursive types,
type some_other_type
type a = {
x: some_other_type;
next: b
}
and b =
NoA
| SomeA of a;;
Or, alternatively, break the dependency by making one of the types polymorphic, e.g.,
type some_other_type
type 'b a = {
x: some_other_type;
next: 'b
}
type b =
NoA
| SomeA of b a;;
Or
type some_other_type
type 'a b =
NoA
| SomeA of 'a
type a = {
x: some_other_type;
next: a b
}
Upvotes: 5
Reputation: 11372
You need to define the two types together using and
:
type a = {
x: some_other_type;
next: b
}
and b =
NoA
| SomeA of a;;
Upvotes: 3