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
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