En Haskell, le newtype est un type équivalent, mais non compatible :
newtypeMyInt=MyIntInt
Après on peut convertir un Int en MyInt de plusieurs manière, en utilisant le constructeur, par pattern matching ou via des casts sécurisés.
Dans d'autres langages, ce serait contraignant car il faudrait écrire toutes les méthodes / fonctions associées. En haskell, on peut lui demander de dériver automatiquement tout comportement (class) implementée par le sous type.
Exemple, si on veut faire un sous type qui se comporte comme un String (au moins pour certaines opérations) mais qui n'est pas compatible avec une String:
Monoid fournissant la concaténation de chaîne via (<>), Show fournissant l'affichage. Eq et Ord fournissant respectivement les relations d'égalité et d'ordre. Cet exemple utilise l'extension GeneralizedNewtypeDeriving.
Ce genre de chose est malheureusement difficile à réaliser dans d'autre langage, et souvent il faut réaliser une classe englobante et propager toutes les méthodes intéressantes, c'est beaucoup de code lourd pour pas grande chose.
En C++ on peut s'en sortir avec des types phantoms :
structTagColor{};structTagPosition{};structTagDirection{};template<typenameTag>structPoint3{floatx,y,z;Point3<Tag>operator+(Point3<Tag>&other){return{x+other.x,y+other.y,z+other.z};};};usingColor=Point3<TagColor>;usingPosition=Point3<TagPosition>;usingDirection=Point3<TagDirection>;intmain(){Colorc{1,1,0};Colorc2{0,0,1};Colorc3=c+c2;Positionp{0,0,0};// Erreur de compilation, on ne peut pas additionner un point et une couleurPositionp2=p+c;}
Mais cette solution devient vite embêtante quand on veut pouvoir définir un sous ensemble d'opération pour chaque type. Par exemple, l'addition entre deux couleurs peut avoir du sens, alors qu'entre deux positions ?
À ce niveau, la meilleur solution que je connaisse c'est de faire une classe Point qui contient toutes les opérations nécessaires, et des classes Position, Direction, Couleur qui encapsulent un Point de manière privée et qui n'exposent que les fonctions nécessaires.
[^] # Re: Go
Posté par Guillaum (site web personnel) . En réponse au journal Une petite histoire d'utilisation type fort dans Ocaml. Évalué à 5.
C'est cool ça.
En Haskell, le
newtypeest un type équivalent, mais non compatible :Après on peut convertir un
IntenMyIntde plusieurs manière, en utilisant le constructeur, par pattern matching ou via des casts sécurisés.Dans d'autres langages, ce serait contraignant car il faudrait écrire toutes les méthodes / fonctions associées. En haskell, on peut lui demander de dériver automatiquement tout comportement (
class) implementée par le sous type.Exemple, si on veut faire un sous type qui se comporte comme un
String(au moins pour certaines opérations) mais qui n'est pas compatible avec uneString:Monoidfournissant la concaténation de chaîne via(<>),Showfournissant l'affichage.EqetOrdfournissant respectivement les relations d'égalité et d'ordre. Cet exemple utilise l'extensionGeneralizedNewtypeDeriving.Ce genre de chose est malheureusement difficile à réaliser dans d'autre langage, et souvent il faut réaliser une classe englobante et propager toutes les méthodes intéressantes, c'est beaucoup de code lourd pour pas grande chose.
En C++ on peut s'en sortir avec des types phantoms :
Mais cette solution devient vite embêtante quand on veut pouvoir définir un sous ensemble d'opération pour chaque type. Par exemple, l'addition entre deux couleurs peut avoir du sens, alors qu'entre deux positions ?
À ce niveau, la meilleur solution que je connaisse c'est de faire une classe
Pointqui contient toutes les opérations nécessaires, et des classesPosition,Direction,Couleurqui encapsulent unPointde manière privée et qui n'exposent que les fonctions nécessaires.