Systèmes de types: nominal vs structurel, explicite vs implicite


24

Je suis un peu confus quant à la différence entre les systèmes de type nominal et structurel. Quelqu'un peut-il expliquer en quoi ils diffèrent?

D'après ce que je comprends:

  • Nominal: la compatibilité des types est basée sur le nom du type.
  • Structurel: la compatibilité de type est basée sur la structure de type, par exemple en C si 2 variables sont des types de structure avec des noms différents mais la même structure, alors leurs types sont compatibles.

Maintenant explicite et implicite: pourquoi est-il différent du typage statique et dynamique? En typage statique, les types seront explicites tandis qu'en typage dynamique, les types sont implicites. Ai-je raison?

Réponses:


29

Dans un système typé dynamiquement, les valeurs ont des types à l'exécution, mais pas les variables et les fonctions. Dans un système typé statiquement, les variables et les fonctions ont des types connus et vérifiés au moment de la compilation. Par exemple, en Python xpeut être n'importe quoi ; à l'exécution, si c'est 1un nombre et s'il l'est "foo", c'est une chaîne. Vous ne sauriez que quel type xétait à l'exécution, et il pourrait être différent à chaque fois que vous exécutez le programme. Dans un langage comme Java, vous écririez int xif xdevait être un nombre, et vous sauriez au moment de la compilation que cela xdoit toujours être un int.

Les types "explicites" et "implicites" se réfèrent tous deux à des systèmes de types statiques . La caractéristique qui définit un système statique est que les types sont connus au moment de la compilation, mais pas nécessairement qu'ils doivent être écrits. En Java, les types sont explicites - vous devez les écrire. Ainsi, en Java, une méthode pourrait ressembler à quelque chose comme:

public int foo(String bar, Object baz) { ... }

Les types sont à la fois connus au moment de la compilation (statiques) et écrits (explicites). Cependant, il y a aussi des langues qui ne pas vous forcer à écrire le type out. Ils peuvent déduire le type d'une fonction de son corps et comment elle est utilisée. Un exemple serait OCaml, où vous pouvez écrire quelque chose comme:

let foo x = x + 1

Depuis que vous l'avez utilisé +, OCaml peut comprendre que cela xdoit être un inttout seul. Le type de foo( foo : int -> int) est donc connu au moment de la compilation, tout comme l'exemple Java. C'est entièrement statique. Cependant, puisque le compilateur peut déterminer ce que les types doivent être par lui-même, vous n'avez pas à les écrire vous-même: ils sont implicites.

En bref: si un système de type est explicite ou implicite est une propriété des systèmes statiques . C'est une question complètement différente de savoir si un système de type est dynamique ou statique.

Souvent, vous avez des systèmes de types qui sont parfois explicites et parfois implicites.

Par exemple, je pense que C # vous permet de déduire des types à l'aide du varmot clé. Donc, au lieu d'écrire int x = 10, vous pouvez écrire var x = 10et le compilateur doit comprendre que cela xdoit être un int. C ++ fait quelque chose de similaire avec auto. Ces systèmes sont généralement explicites mais ont une certaine inférence.

D'un autre côté, il existe des systèmes qui sont généralement implicites mais vous obligent parfois à écrire une signature de type. Haskell en est un excellent exemple. La plupart du temps, Haskell peut déduire les types pour vous. Cependant, parfois, vous pouvez écrire du code ambigu comme show . read, où Haskell ne peut pas comprendre les types par lui-même. Dans ce cas, vous seriez obligé de spécifier explicitement le type de showou read. De plus, certaines fonctionnalités plus avancées du système de types (comme le polymorphisme de rang n) rendent l'inférence indécidable - c'est-à-dire qu'il n'est pas garanti qu'elle s'arrête. Cela signifie que le code utilisant cette fonctionnalité nécessite souvent des signatures de type explicites.


2
En fait, il existe certaines langues avec ce que vous pourriez appeler une frappe dynamique explicite . En règle générale, ces langues vous permettent d'annoter des expressions avec des types, puis ces types seront vérifiés lors de l'exécution par rapport au type d'exécution de l'expression.
Jörg W Mittag

juste une précision: les systèmes de types ne sont ni implicites ni explicites. Il s'agit simplement d'inférence de type, qui est essentiellement un moyen de générer des termes valides dans un système de type à partir d'une syntaxe différente (parfois non spécifiée).
Eduardo Pareja Tobes

Bonne réponse, mais cela ne traite pas du typage nominal vs structurel. Un montage serait génial.
lunchmeat317

7
  • statique vs dynamique décrit quand les types sont vérifiés (plus ou moins au moment de la compilation ou au moment de l'exécution)

  • nominal vs structurel décrit quand deux types sont considérés comme identiques.

(Et il existe des variantes, la plus connue est la variante du typage structurel qui ne prend en compte que ce qui est utilisé au lieu du type entier appelé typage canard).

Les quatre combinaisons (nominal statique, structurel statique, nominal dynamique, structurel dynamique) sont possibles, et les langues ne sont souvent pas purement dans une classe mais ont des aspects qui sont dans d'autres.

Par exemple, les systèmes de types de C ++ sont statiques, principalement nominaux mais structurels lorsque vous considérez les modèles (et vous pouvez considérer une partie des problèmes liés aux concepts en C ++ comme un conflit entre ceux qui souhaitent passer du typage canard à une forme complète de typage structurel et ceux qui veulent passer à la frappe nominale). Et l'utilisation des classes et de l'héritage permet d'utiliser un typage dynamique et nominal dans certains cas.

Langage qu'un système de type dynamique utilise souvent le typage structurel, mais CLOS comme aspects nominaux.


1

Structurel: la compatibilité de type est basée sur la structure de type, par exemple en C si 2 variables sont des types de structure avec des noms différents mais la même structure, alors leurs types sont compatibles.

Ce n'est généralement pas le cas. Le typage structurel signifie qu'il Bs'agit d'un sous-type de As'il peut satisfaire Al'interface de. Cela signifie généralement avoir des membres du même nom; pas seulement la même structure en mémoire.

Cela diffère du typage nominatif qui nécessite que les super-types soient spécifiés lors de la déclaration.


1

La meilleure explication que j'ai vue de la distinction entre (en fait la subsomption des) systèmes de type dynamique et statique est dans cet article de blog de Bob Harper:

Son principal point pourrait être résumé comme suit:

  • les langues dynamiques sont les langues statiques avec un seul type

1
Les liens peuvent mal tourner; vous devez citer les parties les plus pertinentes de l'article afin qu'elles soient préservées pour la postérité, même si le blog devient kaput.
Doval

2
Sûr. Je pense que dans ce cas la phrase que j'ai ajoutée suffit :)
Eduardo Pareja Tobes
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.