I have a function that takes a list of tuples and process it to obtain a tuple of 3 integers. I would now like to test it with a list of the tuples type I created but I'm unable to create this list.
Here is my tuple type :
type t_votes = {valeur : string ; nombre : int };;
Here is my function :
let rec recap (l : t_votes list) : int * int * int =
let (nb_oui,nb_non,nb_blanc) = recap(tl(l)) in
if (l=[]) then
(0,0,0)
else if ((hd(l)).valeur = "oui") then
(nb_oui+(hd(l)).nombre ,nb_non,nb_blanc)
else if ((hd(l)).valeur = "non") then
(nb_oui, nb_non + (hd(l)).nombre, nb_blanc)
else if ((hd(l)).valeur = "blanc") then
(nb_oui,nb_non,nb_blanc+(hd(l)).nombre)
else
failwith("liste invalide")
;;
And here is my vain attempt at declaring a list to test my function with :
let liste_votes : t_votes list = [("oui",120);("non",18);("blanc",20);("oui",20);("non",24);("blanc",25)];;
recap(liste_votes );;
Here is what tuareg gives me :
# let liste_votes : t_votes list = [("oui",120);("non",18);("blanc",20);("oui",20);("non",24);("blanc",25)];;
Characters 34-45:
let liste_votes : t_votes list = [("oui",120);("non",18);("blanc",20);("oui",20);("non",24);("blanc",25)];;
^^^^^^^^^^^
Error: This expression has type 'a * 'b
but an expression was expected of type t_votes
To create a value of a record type (because it is a record type and not a tuple, a tuple doesn't name its arguments), the syntax is the following:
{ valeur = "Some string" ; nombre = 13 }
If this syntax is too heavy for you, a common practice is to write a builder function:
let mk_vote valeur nombre = { valeur ; nombre }
Here I'm using another piece of syntax to instantiate a record value without using the =
symbol. In that case, it's the same as writing valeur = valeur
and nombre = nombre
.
You can then write:
let votes = [ mk_vote "oui" 120 ; mk_vote "non" 18 ; mk_vote "blanc" 20 ; mk_vote "oui" 20 ; mk_vote "non" 24 ; mk_vote "blanc" 25 ]
let mk_vote (valeur, nombre) = { valeur ; nombre }
would work as well and let you write
let votes = List.map mk_vote [("oui",120);("non",18);("blanc",20);("oui",20);("non",24);("blanc",25)]
For some vote
of the record type you can access the fields with vote.valeur
and vote.nombre
.
You can also use pattern-matching:
match vote with
| { valeur = v ; nombre = n } => (* ... *)
You can also make a record value from another one like so:
let vote = { valeur = "Some string" ; nombre = 13 } in
let vote' = { vote with valeur = "Some other string" } in
(* ... *)
Then vote'.valeur
is "Some other string"
while vote'.nombre
is vote.nombre
,
or 13
in that case.
Finally I couldn't help but notice you were using strings to represent different kind of votes, since there seem to be only three cases, a dedicated type would be more relevant (you are using ocaml after all which lets you handle data properly).
type vote_kind =
| Yes
| No
| Blank
type t_votes = {
value : vote_kind ;
amount : int ;
}