'weak type Problem

Hello !
I’m doing my homework and I don’t understand why is an object type 'a weak…
This is the code I typed:

type 'a elem_fp = {valeur: 'a; prio: int};;

type 'a elem_dict = {cle: int; valeur: 'a};;

type 'a case_tab =
	| Vide
	| E of 'a elem_dict;;

type 'a dict3 = {
	tab: 'a case_tab array;
	mutable nb_elem: int;
};;

let create_d3 (m: int): 'a dict3 = {
	tab = Array.make m Vide;
	nb_elem = 0};;

create_d3 5;;

This is the log (just have a look at the bold text):

# type 'a elem_fp = {valeur: 'a; prio: int};;
type 'a elem_fp = { valeur : 'a; prio : int; }
# type 'a elem_dict = {cle: int; valeur: 'a};;
type 'a elem_dict = { cle : int; valeur : 'a; }
# type 'a case_tab =
type 'a case_tab = Vide | E of 'a elem_dict
# type 'a dict3 = {
type 'a dict3 = { tab : 'a case_tab array; mutable nb_elem : int; }
# let create_d3 (m): 'a dict3 = {
val create_d3 : int -> 'a dict3 =
# create_d3 8;;
- : '_weak1 dict3 =
{tab = [|Vide; Vide; Vide; Vide; Vide; Vide; Vide; Vide|]; nb_elem = 0}
# create_d3 5;;
- : '_weak2 dict3 = {tab = [|Vide; Vide; Vide; Vide; Vide|]; nb_elem = 0}
# let create_d3 (m: int): 'a dict3 = {
val create_d3 : int -> 'a dict3 =
# create_d3 5;;
- : '_weak3 dict3 = {tab = [|Vide; Vide; Vide; Vide; Vide|]; nb_elem = 0}

My function has a correct type, but why has the dict3 such a type??

Thank you for your answers,
Koelite.

The type _weak1 is a placeholder for a concrete type. You can make it disappear by precising the concrete type at creation

let a: int dict3  = create_d3 5

Or by using the dictionary in a context where the concrete type is clear;

let a = create_d3
let () = a.tab.(0) <- E {cle=0; valeur=1 }

If you want to know why you got a weakly polymorphic type, you can read the corresponding manual section.
In brief, arrays are mutable, so the types of their contents cannot be polymorphic. For instance, consider:

let a = Array.make 1 None
let read a = match a.(0) with
| None -> "none"
| Some x ->  "Some " ^ x
let () = a.(0) <- Some 5
let b = read a

The second read ought to be a type error because the contents of a.(0) is an int option not a string option.
To deal with this kind of issues, polymorphic mutable values are assigned a weakly polymorphic type when they are created.

2 Likes

Thank you very much!

I’ll add to @octachron’s excellent answer that the return type constraint of 'a dict3 in the following snippet probably isn’t doing what you think it’s doing:

let create_d3 (m: int): 'a dict3 = {
	tab = Array.make m Vide;
	nb_elem = 0};;

This says: "the function must return a dict3 of some type 'a", which may be any type. In this case, that will be a weakly polymorphic type variable as @octachron said, but in practice it could be any type:

(* my_dict definitely contains strings, but the constraint is valid *)
let my_dict : 'a dict3 = {
  tab = [| E {cle = 0; valeur = "foo"} |];
  nb_elem = 1
};;

> val my_dict : string dict3 = ...

This is a bit of a ‘gotcha’ with type constraints.

1 Like