Вивід типів

Ви́від ти́пів (англ. type inference) — в програмуванні можливість компілятора самому логічно вивести тип значення у виразу. Вперше механізм виведення типів був представлений в мові ML, де компілятор завжди виводить найзагальніший поліморфний тип для будь-якого виразу. Це не тільки скорочує розмір початкового коду і підвищує його лаконічність, але і часто підвищує повторне використання коду[1].

Вивід типів є характерним для функціональних мов програмування, хоча з часом ця можливість частково з'явилася і в об'єктно-орієнтованих мовах програмування (C#, D, Visual Basic .NET, C++11, Vala, Go), де вона обмежується можливістю опустити тип ідентифікатора у визначенні з ініціалізацією (див. синтаксичний цукор). Наприклад:

var s = "Hello, world!";  // Тип змінної s (string) виведений з ініціалізатора 

Алгоритми[ред. | ред. код]

Алгоритм Гіндлі – Мілнера[ред. | ред. код]

Алгоритм Гіндлі – Мілнера — механізм виводу типів виразів, який реалізується в мовах програмування, які базуються на системі типів Гіндлі – Мілнера[en], таких як ML (перша мова цього сімейства), Standard ML, OCaml, Haskell, F#, Fortress та Boo. Мова Nemerle використовує цей алгоритм з рядом необхідних змін[2].

Механізм виведення типів базується на можливості автоматично повністю або частково виводити тип виразу, отриманого за допомогою обчислення деякого виразу. Оскільки цей процес систематично проводиться під час трансляції програми, транслятор часто може вивести тип змінної або функції без явного вказування типів цих об'єктів. В багатьох випадках можна опускати явні декларації типів — це можна робити для достатньо простих об'єктів, або для мов з простим синтаксисом. Наприклад, в мові Haskell реалізований достатньо потужний механізм виведення типів, тому явного вказування типів функцій в цій мові програмування не потрібно. Програміст може вказати тип функції явно для того, щоб обмежити її використання тільки для конкретних типів даних, або для більш структурованого оформлення початкового коду.

Для того, щоб отримати інформацію для коректного виведення типу виразу в умовах відсутності явної декларації типу цього виразу, транслятор або збирає таку інформацію з явних декларацій типів підвиразів (змінних, функцій), які входять до виразу, що вивчається, або використовує неявну інформацію про типи атомарних значень. Такий алгоритм не завжди допомагає визначити тип виразу, особливо у випадку використання функцій вищих порядків і параметричного поліморфізму достатньо складної природи. Тому в складних випадках, коли виникає необхідність уникнути неоднозначностей, рекомендується явно вказувати тип виразів.

Сама модель типізації базується на алгоритмі виведення типів виразів, який має як джерело механізм отримання типів виразів, що використовується в типізованому λ-численні, який був запропонований в 1958 році Г. Каррі і Р. Фейсом. Далі вже Роджер Гіндлі[en] в 1969 році розширив сам алгоритм і довів, що він виводить найзагальніший тип виразу. В 1978 році Робін Мілнер незалежно від Р. Гіндлі довів властивості еквівалентного алгоритму. І, нарешті, в 1985 році Луіс Дамас остаточно показав, що алгоритм Мілнера є завершеним і може використовуватись для поліморфних типів. У зв'язку з цим алгоритм Гіндлі – Мілнера інколи називають також і алгоритмом Дамаса – Мілнера.

Система типів визначається в моделі Гіндлі – Мілнера наступним чином:

  1. Примітивні типи є типами виразів.
  2. Параметричні змінні типів α є типами виразів.
  3. Якщо і  — типи виразів, то тип є типом виразів.
  4. Символ є типом виразів.

Вирази, типи яких обчислюються, визначаються досить стандартним чином:

  1. Константи є виразами.
  2. Змінні є виразами.
  3. Якщо і  — вирази, то () — вираз.
  4. Якщо  — змінна, а  — вираз, то  — вираз.

Кажуть, що тип є екземпляром типу , коли існує деяке перетворення таке, що:

При цьому зазвичай вважається, що на перетворення типів накладаються обмеження, які полягають в тому, що:

Сам алгоритм виведення типів складається з двох кроків — генерування системи рівнянь і наступне розв'язування цих рівнянь.

Побудова системи рівнянь[ред. | ред. код]

Побудова системи рівнянь базується на наступних правилах:

  1.  — в тому випадку, якщо зв'язування знаходиться в .
  2.  — в тому випадку, якщо , де і .
  3.  — в тому випадку, якщо і є розширенням зв'язуванням .

В цих правилах під символом розуміється набір зв'язувань змінних з їх типами (середовище типізації):

Розв'язування системи рівнянь[ред. | ред. код]

Розв'язування побудованої системи рівнянь базується на алгоритмі уніфікації. Це достатньо простий алгоритм. Є деяка функція , яка приймає на вхід рівняння типів і повертає деяку підстановку. Підстановка — це просто проєкція змінних типів на самі типи. Такі підстановки можуть обчислюватись різними способами, які залежать від конкретної реалізації алгоритму Гіндлі – Мілнера.

Див. також[ред. | ред. код]

Примітки[ред. | ред. код]

  1. Andrew W. Appel. A Critique of Standard ML // Princeton University, revised version of CS-TR-364-92. — 1992.(англ.)
  2. Michał Moskal. Type Inference with Deferral // Institute of Computer Science, University of Wrocław. — 2005. Архівовано з джерела 4 березня 2016. Процитовано 29 липня 2015.(англ.)

Посилання[ред. | ред. код]