Если вы знаете C ++, легко привести мотивирующий пример:
Допустим, у нас есть некоторый тип контейнера и два его экземпляра
typedef std::map<int,int> IIMap;
IIMap foo;
IIMap bar;
и рассмотрим этот фрагмент кода (выможет предполагать, что foo не пусто):
IIMap::iterator i = foo.begin();
bar.erase(i);
Это очевидный мусор (и, вероятно, повреждает структуры данных), но он прекрасно проверит тип, так как "итератор в foo" и "итератор вbar "одного типа, IIMap::iterator
, даже если они семантически несовместимы.
Проблема в том, что тип итератора должен зависеть не только от контейнера type , но на самом делев контейнере объект , т. е. это должен быть «нестатический тип элемента»:
foo.iterator i = foo.begin();
bar.erase(i); // ERROR: bar.iterator argument expected
Такая функция, возможность выражать тип (foo.iterator), которыйзависит от термина (foo), это именно то, что означает зависимая типизация.
Причина, по которой вы не часто видите эту функцию, заключается в том, что она открывает большую банку с червями: вы неожиданно попадаете в ситуации, когдапроверить во время компиляцииНезависимо от того, являются ли два типа одинаковыми, вам в конечном итоге придется доказать, что два выражения эквивалентны (всегда будет давать одно и то же значение во время выполнения).В результате, если вы сравните список википедии с зависимой типизацией со списком доказательств теорем , вы можете заметить подозрительное сходство.; -)