Certes, mais même lorsque l'on fait du typage statique et que l'on utilise un algorithme d'unification, il est possible de renvoyer des messages plus compréhensibles. Le papier auquel tu renvoies donne des pistes, mais le message de Guillaume Denry sur elm est encore plus parlant. Elm a un système de type à la Haskell et son message d'erreur est on ne peut plus compréhensif et informatif.
Comme ces derniers temps je joue un peu avec Coq, qui doit faire face à des problématiques d'unification à coté desquelles celles de Rust sont un jeu d'enfant, je vais donner des exemples dans ce langage.
Pour commencer, il semblerait naturel de n'utiliser une notation infixe x + y que dans une structure de monoïde. Alors je vais le faire façon type classes à la Haskell :
Elle prend deux valeurs d'un certain type ?A et renvoie une valeur de ce type, et cela dans un contexte où ce type est connu avec un monoïde sur les valeurs de ce type (le ? signifie que le terme est indéterminé, la variable est existentielle : il existe une valeur A telle que ...). Si on lui demande de typer l'expression 1 +' "3a", on obtient :
Check1+'"3a".(* ==>Error:The term ""3a"" has type "string" while it is expected to have type "nat". *)
Mais le plus amusant est qu'il peut typer le terme "1" +' "3a" avant même de savoir le calculer :
Maintenant pour lui permettre de calculer, on lui fournit une instance de la classe :
(* on prouve que le type string muni de l'opération de concaténation est un monoïde dont l'élément neutre est la chaîne vide. *)InstanceStr_append:monoidappend"".Proof.split.-inductionx;[auto|intros;simpl;rewriteIHx;reflexivity].-reflexivity.-inductionx;[auto|simpl;rewriteIHx;reflexivity].Qed.(* maintenant on vérifie le type et on évalue : *)Check"1"+'"3a".(* ==>"1" +' "3a" : string *)Evalcomputein"1"+'"3a".(* ==> = "13a" : string *)
Pour le cas plus général où les deux opérandes ne sont pas du même type (et l'on se demande bien alors pourquoi utiliser la notation additive ?), et revenir à la situation de python, je vais l'illustrer ainsi.
Là on est dans la situation de python : comme il fait du typage dynamique, lors de l'appel au calcul de l'expression il vérifie si l'environnement permet de bien typer le terme (s'il peut instancier ces variables existentielles). Comme ce langage permet de modifier dynamiquement l'environnement, il est impossible de refuser statiquement ce code. Il pourrait, par exemple, être défini dans une bibliothèque où le code ne peut être évalué, puis importer dans un code qui rend l'évaluation possible. Comme dans le dialogue suivant avec la REPL Coq :
Evalcomputein1+'"3a".(* ==> = ?bin_op 1 "3a" : ?C *)(* ici l'évaluation totale génère une erreur : le typage étant statique, il exige d'être dans un environnement où les variables existentielles sont instanciées. *)Evalvm_computein1+'"3a".(* ==>Error: vm_compute does not support existential variables. *)Instancenat_add:bin_opnatnatnat:={op:=plus}.Instancestr_app:bin_opstringstringstring:={op:=append}.Instancenat_str:bin_opnatstringstring:={opns:=matchgetnswith|None=>""|Somec=>Stringc""end}.Evalvm_computein1+'3.(* ==> 4 : nat *)Evalvm_computein"1"+'"3a".(* ==> "13a" : string *)Evalvm_computein1+'"3a".(* ==> "a" : string, à la manière du C *)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Un peu déçu par Rust
Posté par kantien . En réponse au journal Un print(1 + "3a"), ça nous inspire comment ?. Évalué à 5.
Certes, mais même lorsque l'on fait du typage statique et que l'on utilise un algorithme d'unification, il est possible de renvoyer des messages plus compréhensibles. Le papier auquel tu renvoies donne des pistes, mais le message de Guillaume Denry sur elm est encore plus parlant. Elm a un système de type à la Haskell et son message d'erreur est on ne peut plus compréhensif et informatif.
Comme ces derniers temps je joue un peu avec Coq, qui doit faire face à des problématiques d'unification à coté desquelles celles de Rust sont un jeu d'enfant, je vais donner des exemples dans ce langage.
Pour commencer, il semblerait naturel de n'utiliser une notation infixe
x + yque dans une structure de monoïde. Alors je vais le faire façon type classes à la Haskell :Là on fait un type checking sur la fonction
monoid_op:Elle prend deux valeurs d'un certain type
?Aet renvoie une valeur de ce type, et cela dans un contexte où ce type est connu avec un monoïde sur les valeurs de ce type (le?signifie que le terme est indéterminé, la variable est existentielle : il existe une valeurAtelle que ...). Si on lui demande de typer l'expression1 +' "3a", on obtient :Mais le plus amusant est qu'il peut typer le terme
"1" +' "3a"avant même de savoir le calculer :Maintenant pour lui permettre de calculer, on lui fournit une instance de la classe :
Pour le cas plus général où les deux opérandes ne sont pas du même type (et l'on se demande bien alors pourquoi utiliser la notation additive ?), et revenir à la situation de python, je vais l'illustrer ainsi.
Là on est dans la situation de python : comme il fait du typage dynamique, lors de l'appel au calcul de l'expression il vérifie si l'environnement permet de bien typer le terme (s'il peut instancier ces variables existentielles). Comme ce langage permet de modifier dynamiquement l'environnement, il est impossible de refuser statiquement ce code. Il pourrait, par exemple, être défini dans une bibliothèque où le code ne peut être évalué, puis importer dans un code qui rend l'évaluation possible. Comme dans le dialogue suivant avec la REPL Coq :
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.