Параметричний поліморфізм — Вікіпедія

У мовах програмування та теорії типів параметричний поліморфізм дозволяє одному й тому ж коду отримувати "загальний" тип із використанням змінних замість конкретних типів, які можуть бути підставлені за потреби.[1]:340 Параметрично поліморфні функції та типи даних іноді називають відповідно узагальненими функціями та узагальненими типами даних. Вони є основою узагальненого програмування.

Параметричний поліморфізм може бути протиставлений ad hoc поліморфізму. Параметрично поліморфні визначення є універсальними: вони поводяться однаково незалежно від того, для якого типу вони інстанційовані.[1]:340[2]:37 На відміну від цього, визначення ad hoc поліморфізму створюються окремо для кожного типу. Таким чином, ad hoc поліморфізм зазвичай підтримує лише обмежену кількість таких окремих типів, оскільки для кожного типу потрібна окрема реалізація.

Основне визначення

[ред. | ред. код]

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

Параметрично поліморфне визначення потім може бути інстанційоване шляхом підстановки будь-якого конкретного типу замість , що утворює повне сімейство можливих типів.[3]

Тотожна функція є надзвичайним прикладом, але багато інших функцій також виграють від параметричного поліморфізму. Наприклад, функція , яка з’єднує два списки, не аналізує елементи списку, а працює лише зі структурою самого списку. Тому може мати подібну сім'ю типів, таких як , тощо, де позначає список елементів типу . Найзагальніший тип, таким чином, виглядає так:

Цей тип може бути інстанційований для будь-якого типу з сім'ї.

Параметрично поліморфні функції, такі як і , кажуть, що вони параметризовані довільним типом .[4] Обидві функції і параметризовані одним типом, але функції можуть бути параметризовані довільною кількістю типів. Наприклад, функції і , які повертають перший і другий елементи пари, відповідно, можуть мати такі типи:

У виразі тип інстанційований як , а — як у виклику . Тому тип усього виразу є .

Синтаксис, який використовується для введення параметричного поліморфізму, значно відрізняється між мовами програмування. Наприклад, у деяких мовах програмування, таких як Haskell, квантор є неявним і може бути опущеним.[5] Інші мови вимагають явно визначати типи в деяких або всіх точках виклику параметрично поліморфної функції.

Історія

[ред. | ред. код]

Параметричний поліморфізм вперше був введений у мови програмування в ML у 1975 році.[6] Сьогодні він існує у Standard ML, OCaml, F#, Ada, Haskell, Mercury, Visual Prolog, Scala, Julia, Python, TypeScript, C++ та інших. Java, C#, Visual Basic .NET та Delphi також додали підтримку "дженериків" для параметричного поліморфізму. Деякі реалізації типового поліморфізму зовнішньо схожі на параметричний поліморфізм, але також включають елементи ад-хок. Наприклад, C++ підтримує спеціалізацію шаблонів.

Предикативність, імпредикативність і поліморфізм вищого рангу

[ред. | ред. код]

Поліморфізм 1-го рангу (предикативний)

[ред. | ред. код]

У предикативній типізованій системі (також відомій як пренексний поліморфізм), змінні типів не можуть бути замінені на поліморфні типи.[1]: Предикативні теорії типів включають теорію типів Мартіна-Льофа та Nuprl. Це дуже схоже на так званий "ML-стиль" або "Let-поліморфізм" (технічно Let-поліморфізм у ML має кілька інших синтаксичних обмежень). Це обмеження робить розрізнення між поліморфними і неполіморфними типами дуже важливим; таким чином, у предикативних системах поліморфні типи іноді називають схемами типів, щоб відрізняти їх від звичайних (монополіморфних) типів, які іноді називають монотипами.

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

Щоб застосувати цю функцію до пари списків, необхідно підставити конкретний тип замість змінної так, щоб отриманий тип функції відповідав типам аргументів.

В імпредикативній системі може бути будь-яким типом, включаючи тип, який сам є поліморфним; таким чином, можна застосовувати до пар списків із елементами будь-якого типу — навіть до списків поліморфних функцій, таких як сама . Поліморфізм у мові ML є предикативним.[джерело?] Це тому, що предикативність разом з іншими обмеженнями робить систему типів настільки простою, що повне виведення типів завжди можливе.

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

Поліморфізм вищого рангу

[ред. | ред. код]

Деякі системи типів підтримують імпредикативний конструктор функційного типу, навіть якщо інші конструктори типів залишаються предикативними. Наприклад, тип дозволений у системі, яка підтримує поліморфізм вищого рангу, навіть якщо тип може бути недоступним.[7]

Тип вважається типом рангу k (для деякого цілого числа k), якщо жоден шлях від його кореня до квантора не проходить зліва від k або більше стрілок, якщо тип зображений як дерево.[1]:359 Система типів підтримує поліморфізм рангу k, якщо вона дозволяє типи з рангом, що не перевищує k. Наприклад, система типів, яка підтримує поліморфізм рангу 2, дозволяє тип , але не . Система типів, яка допускає типи будь-якого рангу, називається "ранг-n поліморфною".

Вивід типів для поліморфізму рангу 2 є вирішуваним, але для рангів 3 і вище — ні.[8][1]:359

Імпредикативний поліморфізм

[ред. | ред. код]

Імпредикативний поліморфізм (також відомий як поліморфізм першого класу) є найпотужнішою формою параметричного поліморфізму.[1]:340 У формальній логіці визначення називається імпредикативним, якщо воно є самореференційним; у теорії типів це стосується можливості, щоб тип знаходився в області дії квантора, який його містить. Це дозволяє підстановку будь-якої змінної типу будь-яким типом, включно з поліморфними типами. Прикладом системи, яка підтримує повну імпредикативність, є System F, що дозволяє підстановку для будь-якого типу, включно із самим собою.

У теорії типів найчастіше досліджуваними імпредикативними типізованими λ-численнями є ті, що базуються на лямбда-куб, особливо System F.

Обмежений параметричний поліморфізм

[ред. | ред. код]

У 1985 році Лука Карделлі та Пітер Вегнер визнали переваги дозволу обмежень на параметри типу.[9] Багато операцій вимагають певних знань про типи даних, але можуть працювати параметрично. Наприклад, щоб перевірити, чи міститься елемент у списку, потрібно порівняти елементи на рівність. У Standard ML параметри типу форми ’’a обмежені так, щоб операція рівності була доступною; відповідно, функція має тип ’’a × ’’a list → bool, і ’’a може бути лише типом із визначеною рівністю. У Haskell обмеження досягається за допомогою вимоги, щоб типи належали до певного типового класу; отже, та сама функція має тип у Haskell. У більшості об'єктно-орієнтованих мов програмування, які підтримують параметричний поліморфізм, параметри можуть бути обмежені підтипами певного типу (див. статті Підтиповий поліморфізм і Узагальнене програмування).

Примітки

[ред. | ред. код]
  1. а б в г д е Бенджамін К. Пірс (2002). Types and Programming Languages. MIT Press. ISBN 978-0-262-16209-8.
  2. Strachey, Christopher (1967), Fundamental Concepts in Programming Languages (Lecture notes), Copenhagen: International Summer School in Computer Programming. Перевидано у: Strachey, Christopher (1 квітня 2000). Fundamental Concepts in Programming Languages. Higher-Order and Symbolic Computation (англ.). 13 (1): 11—49. doi:10.1023/A:1010000313106. ISSN 1573-0557. S2CID 14124601.
  3. Yorgey, Brent. More polymorphism and type classes. www.seas.upenn.edu. Процитовано 1 жовтня 2022.
  4. Wu, Brandon. Parametric Polymorphism - SML Help. smlhelp.github.io. Процитовано 1 жовтня 2022.
  5. Haskell 2010 Language Report § 4.1.2 Syntax of Types. www.haskell.org. Процитовано 1 жовтня 2022. З одним винятком (спеціальний змінний тип у декларації класу (розділ 4.3.1)), змінні типу в Haskell завжди вважаються універсально квантифікованими; синтаксис для універсальної квантифікації відсутній.
  6. Мілнер, Р., Морріс, Л., Ньюї, М. "Логіка для обчислюваних функцій з рефлексивними та поліморфними типами", Proc. Conference on Proving and Improving Programs, Arc-et-Senans (1975)
  7. Kwang Yul Seo. Kwang's Haskell Blog - Higher rank polymorphism. kseo.github.io. Процитовано 30 вересня 2022.
  8. Kfoury, A. J.; Wells, J. B. (1 січня 1999). Principality and decidable type inference for finite-rank intersection types. Proceedings of the 26th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. Association for Computing Machinery. с. 161—174. doi:10.1145/292540.292556. ISBN 1581130953. S2CID 14183560.
  9. Cardelli та Wegner, 1985.

Джерела

[ред. | ред. код]