Reputation: 4816
I've got 2 types of trees:
type ref_tree = Node of int * ref_tree list ref
type tree = Node of int * tree list
I want to write a function convert: ref_tree -> tree
which gets tree with neighbours saved as references to list containing them and outputs a tree where references are changed to normal lists. Here's what I tried:
let rec convert t =
match t with
| Node (x, l) ->
if (!l = []) then Node (x, []) else
Node (x, (List.map convert !l))
But OCaml returns an error when trying to compile it:
if (!l = []) then Node (x, []) else
Error: This expression has type 'a list
but an expression was expected of type tree list ref
Where This expression
points at empty list inside Node (x, [])
. Why is there a type mismatch?
Upvotes: 1
Views: 114
Reputation: 24812
The problem here is that you define two constructor Node
, with the second definition (type tree = Node of …
) shadowing the first one.
This means that when you're matching against t
and destructuring it as
Node(x, l)
, OCaml sees this as a tree
, not a ref_tree
(and as a consequence sees l
as a tree list
instead of a ref_tree list ref
)
One way to fix this is to change the ref_tree
constructor :
# type ref_tree = Ref_node of int * ref_tree list ref;;
type ref_tree = Ref_node of int * ref_tree list ref
# let rec convert t =
match t with
| Ref_node (x, l) ->
if (!l = []) then Node (x, []) else
Node (x, (List.map convert !l));;
val convert : ref_tree -> tree = <fun>
(another way would be to define those types in modules Tree
and RefTree
and using Tree.Node
and RefTree.Node
)
Upvotes: 2
Reputation: 7560
The compiler gets confused between your two Node
constructors (one of ref_tree
and one of tree
). You can help it out in various ways, including:
let rec convert t =
match (t : ref_tree) with
| Node (x, l) ->
if (!l = []) then Node (x, []) else
Node (x, (List.map convert !l))
Upvotes: 1