Problème typage OCaml
Résolu
MxFragz
-
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
Bonjour,
Je suis en ce moment sur un projet qui consiste à recoder les fonctions du type List, comme par exemple length, iter, map, etc...
Je ne travaille pas avec des type List mais des types my_list qui sont définis comme ceci :
La définition d'une my_list ce fait donc comme ceci :
Je bloque sur la fonction iter2 qui prend en paramètre une fonction et 2 listes. Pour chaque maillon des listes que je lui passe en va appeler la fonction passée en paramètre avec le N ème maillon des 2 listes. Cela revient en fait à faire ceci :
(pour cet exemple)
Voici donc ma fonction iter2 :
mes fonctions de test :
et voici ma fonction length :
La problème est que ici lorsque je passe deux "int my_list" et la fonction print1 (qui affiche deux int prit en paramètre) tout va bien.
En revanche si je passe une "int my_list" et une "string my_list" avec la fonction print2 (qui affiche 1 int et une string prit en paramètre) j'ai une erreur sur l'apelle de "iter2 print2 l1 l2"..
Le problème est que OCaml reçoit les deux listes et suppose que les deux listes sont de type "a' my_list", alors qu'on a en fait une "a' my_list" et une "b' my_list"..
Comment puis je régler mon problème ? Des idées ?
Cordialement,
Maxime.
Je suis en ce moment sur un projet qui consiste à recoder les fonctions du type List, comme par exemple length, iter, map, etc...
Je ne travaille pas avec des type List mais des types my_list qui sont définis comme ceci :
type 'a my_list = | Item of ('a * 'a my_list) | Empty ;;
La définition d'une my_list ce fait donc comme ceci :
let l1 = Item(1, Item(2, Item(3, Item(4, Empty))));; let l2 = Item("un", Item("deux", Item("trois", Item("quatre", Empty))));;
Je bloque sur la fonction iter2 qui prend en paramètre une fonction et 2 listes. Pour chaque maillon des listes que je lui passe en va appeler la fonction passée en paramètre avec le N ème maillon des 2 listes. Cela revient en fait à faire ceci :
f 1 "un";; f 2 "deux";; f 3 "trois"
(pour cet exemple)
Voici donc ma fonction iter2 :
let iter2 f l1 l2 = let rec iter2_aux f = function | 0,Empty,Empty -> () | 0,Item(current1, next1),Item(current2, next2) -> f current1 current2; iter2_aux f (0, next1, next2) | _,_,_ -> raise(Invalid_argument("iter2")) in iter2_aux f (((length l1) - (length l2)),l1, l2) ;;
mes fonctions de test :
let print1 a b = print_int a; print_int b;; let print2 a b = print_int a; print_endline b;;
et voici ma fonction length :
let length = let rec count_node nb = function | Empty -> nb | Item(current, next) -> count_node (nb + 1) next in count_node 0 ;;
La problème est que ici lorsque je passe deux "int my_list" et la fonction print1 (qui affiche deux int prit en paramètre) tout va bien.
En revanche si je passe une "int my_list" et une "string my_list" avec la fonction print2 (qui affiche 1 int et une string prit en paramètre) j'ai une erreur sur l'apelle de "iter2 print2 l1 l2"..
Le problème est que OCaml reçoit les deux listes et suppose que les deux listes sont de type "a' my_list", alors qu'on a en fait une "a' my_list" et une "b' my_list"..
Comment puis je régler mon problème ? Des idées ?
Cordialement,
Maxime.
1 réponse
Le problème c'est que iter2 n'a pas la signature que tu souhaites.
En effet tu as iter2 : ('_a -> '_a -> 'b) -> '_a my_list -> '_a my_list -> unit
Or tu voudrais (je crois) iter2 : ('a -> 'b -> 'c) -> 'a my_list -> 'b my_list -> 'c my_list
Voici comment on devrait faire (sans avoir besoin ni de length, ni de iter2_aux...)
En effet tu as iter2 : ('_a -> '_a -> 'b) -> '_a my_list -> '_a my_list -> unit
Or tu voudrais (je crois) iter2 : ('a -> 'b -> 'c) -> 'a my_list -> 'b my_list -> 'c my_list
Voici comment on devrait faire (sans avoir besoin ni de length, ni de iter2_aux...)
let rec iter2 f l1 l2 = match (l1,l2) with | Empty,_ -> Empty | _,Empty -> Empty | Item(t1,q1),Item(t2,q2) -> Item(f t1 t2,iter2 f q1 q2);;
En effet tu as iter2 : ('_a -> '_a -> 'b) -> '_a my_list -> '_a my_list -> unit
Or tu voudrais (je crois) iter2 : ('a -> 'b -> 'c) -> 'a my_list -> 'b my_list -> 'c my_list "
En effet, c'est exactement ça le problème, j'ai déjà fait un truc de la même manière que toi, mais le problème est que si l1 est d'un taille différente de l2, iter2 va quand même s'executer jusqu'a la fin d'une des listes, or la fonction système lance une exception dès le début sans faire aucun tour de boucle..!
La problème était la ligne :
Je l'ai remplacé par :
Merci bien pour ton aide !
Cordialement,
Maxime.
Tu fais des tours de "boucles" puisque tu calcules length pour chacune des deux listes...
Je ne vois pas ce qu'il y a de dérangeant à avoir deux listes de tailles différentes, lancer une exception ne me paraît pas la meilleure solution car après tout ça n'a rien de dangereux pour le programme.
Mais si ton problème est résolu tant mieux ;-)