Що таке система типів?


50

Фон

Я проектую мову, як побічний проект. У мене є робочий асемблер, статичний аналізатор і віртуальна машина для цього. Оскільки я вже можу компілювати та запускати нетривіальні програми, використовуючи побудовану інфраструктуру, я подумав над тим, щоб подати презентацію у своєму університеті.

Під час своєї розмови я зазначив, що VM забезпечує систему типів, мене запитали "Для чого ваша система типу? ". Після відповіді мене засміяла людина, яка задала питання.

Таким чином, незважаючи на те, що я майже напевно втрачаю репутацію в питанні цього питання, я звертаюся до програмістів.

Моє розуміння

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

Типи також можуть використовуватися для надання інформації цим людським програмістам. Наприклад, я вважаю цю декларацію:

function sqrt(double n) -> double;

корисніший за цей

sqrt(n)

Перший дає велику кількість інформації: що sqrtідентифікатор є функцією, приймає одиницю doubleяк вхід, а інший виробляє doubleяк вихід. Останнє говорить вам, що це, ймовірно, функція, що приймає один параметр.

Моя відповідь

Отже, після запитання "Для чого ваша система типу?" Я відповів так:

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

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

Наступне запитання було "І як типу присвоюється значення?". Тож я пояснив, що всі значення розміщені у вікні та мають вказівник, який вказує на структуру визначення типу, яка надає інформацію про назву типу, на які повідомлення він відповідає та які типи він успадковує.

Після цього я розсміявся, і мою відповідь було відхилено коментарем "Це не реальна типова система".

Отже - якщо те, що я описав, не кваліфікується як "реальна типова система", що було б? Чи правда ця людина, що те, що я надаю, не можна вважати типовою системою?


19
Коли люди говорять про системи типів, вони зазвичай говорять про статичне введення тексту. Динамічне введення тексту не дуже цікаво для тих людей, які піклуються про типові системи, оскільки це майже нічого не гарантує. Наприклад, яке значення може містити змінна х? Що завгодно.
Doval

7
Мені було б цікаво почути, що вони мали сказати, щоб захистити / пояснити свою реакцію.
Ньютопійський

18
@Doval Динамічне введення може гарантувати, що ви не перейдете до безглуздого стану, зробивши щось на зразок додавання коду 5. Звичайно, це не завадить вам спробувати , але це може принаймні зупинити його насправді і дасть вам змогу зрозуміти, що пішло не так, і вжити коригувальних дій, що справді нетипова мова не може.
8bittree

10
Ця особа поставила під сумнів вашу відповідь на запитання "І як тип присвоюється значенню?". Вони хотіли почути про правила введення тексту, а не діаграми з вікнами та вказівниками. Сміх був абсолютно грубим.
садок

10
Сміється людина, швидше за все, є завзятою якоюсь особливою мовою (сім’єю) із сильною системою типу (Haskell здається популярною), і висміяв би щось менш сильне (і, таким чином, іграшку), ніж це, або більш сильний (і, таким чином, непрактичний), або просто різні. Беручи участь у обговоренні з ревниками небезпечно і марно. Сміх подібний просто такий грубий, що він вказує на подібні глибші проблеми. Вам пощастило, що вони не почали проповідувати ...
Гайд

Відповіді:


30

Все це здається точним описом того, що забезпечують системи. І ваша реалізація здається достатньо розумною для того, що вона робить.

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

Залежно від вашого оточення, людина, можливо, захотів би більше формалізму у вашій системі типу. Вони хочуть знати, що ви можете довести цим, а не що програмісти можуть зробити з цим. На жаль, це досить часто в академічних колах. Хоча науковці роблять такі речі, тому що в системі вашого типу досить легко бути недоліки, які дозволяють уникнути правильності. Можливо, вони помітили одне із них.

Якщо у вас виникли додаткові запитання, " Типи та мови програмування" - це канонічна книга з цього питання і може допомогти вам вивчити деякі суворість, необхідна науковцям, а також частину термінології, яка допоможе описати речі.


3
"Залежно від вашого оточення, людина, можливо, хотів би більше формалізму у вашій системі типу". Це, мабуть, саме так. Я не зосереджувався на тому, що можу довести за допомогою системи типів, а радше думав про це як про інструмент. Дякуємо за книжкову рекомендацію!
Майл

1
@Mael Деякі типи систем використовуються як логіки (див. Логічні рамки ). тому в основному тип дає формули, а програми - докази цих формул (наприклад, тип функції a -> bможна розглядати як значення b , тобто якщо ви даєте мені значення типу, aя можу отримати значення типу b). Однак для того, щоб це було узгоджено, мова повинна бути тотальною і, отже, нетургійною. Таким чином, усі системи типу реального життя насправді визначають непослідовну логіку.
Бакуріу

20

Мені подобається відповідь @ Теластіна особливо через посилання на академічний інтерес до формалізму.

Дозвольте додати до дискусії.

Що таке система типів?

Система типу - це механізм визначення, виявлення та запобігання незаконним станам програми. Він працює шляхом визначення та застосування обмежень. Визначення обмежень є типами , а програми обмеження - це типи , наприклад, у оголошенні змінної.

Визначення типів зазвичай підтримують оператори композиції (наприклад, різні форми сполучень, як у структурах, підкласифікації та диз'юнкції, як у перерахунках, союзах).

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

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

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

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

Досить поширеною системою пропонування системи є надання як статичних, так і динамічних функцій.


Я не думаю, що так звані системи гібридного типу взагалі дуже поширені. Які мови ви маєте на увазі?
садок

2
@gardenhead, можливість скидання не є характеристикою системи статичного типу, тому його зазвичай перевіряють під час виконання динамічно.
Ерік Ейдт

1
@gardenhead: більшість статично набраних мов дозволяють відкласти введення тексту на час виконання, будь то просто з void *покажчиками C (дуже слабкими), динамічними об'єктами C # або екзистенційно кількісно оціненими GADTs Haskell (які дають вам більш сильні гарантії, ніж статично набрані значення у більшості інших мови).
Ліворуч близько

Щоправда, я забув про "кастинг". Але кастинг - це просто милиця для системи слабкого типу.
садок

@gardenhead Як і статичні мови, що надають динамічні параметри, багато динамічних мов забезпечують певне статичне введення тексту. Наприклад, Dart, Python та Hack, всі мають режими чи інструменти для проведення статичного аналізу, засновані на концепції "поступового введення тексту".
IMSoP

14

О людино, я з радістю намагаюся відповісти на це питання якнайкраще. Я сподіваюся, що зможу правильно навести свої думки в порядку.

Як зазначав @Doval і запитуючий зазначив (хоч і грубо), у вас насправді немає типової системи. У вас є система динамічних перевірок за допомогою тегів, яка в цілому набагато слабша, а також набагато менш цікава.

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

Огляд

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

Написання програм із системою типу - це як керування доглядом у м'ятному стані - гальмо спрацьовує, двері безпечно закриваються, двигун змащений маслом і т. Д. Написання програм без системи типу - це як їзда на мотоциклі без шолома та з зробленими колесами з спагетті. Ви абсолютно не маєте контролю над своїм.

Обгрунтувати обговорення, скажімо , у нас є мова з літерним виразом num[n]і str[s]які представляють цифру п і рядок s, відповідно, і примітивні функції plusі concat, з імовірною змістом. Зрозуміло, ви не хочете мати можливість написати щось на кшталт plus "hello" "world"або concat 2 4. Але як ми можемо запобігти цьому? Апріорі , немає способу відрізнити число 2 від рядкового буквального "світу". Ми хотіли б сказати, що ці вирази повинні використовуватися в різних контекстах; вони мають різні типи.

Мови та типи

Давайте трохи відступимо: що таке мова програмування? Загалом, ми можемо розділити мову програмування на два шари: синтаксис та семантику. Їх також називають відповідно статикою і динамікою . Виявляється, типова система необхідна для опосередкування взаємодії між цими двома частинами.

Синтаксис

Програма - дерево. Не обманюйте рядки тексту, який ви пишете на комп'ютері; це лише людиночитані уявлення програми. Сама програма є абстрактним синтаксичним деревом . Наприклад, в C ми можемо написати:

int square(int x) { 
    return x * x;
 }

Це конкретний синтаксис програми (фрагмента). Представлення дерева:

     function square
     /     |       \
   int   int x    return
                     |
                   times
                  /    \
                 x      x

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

Семантика

Гаразд, ми знаємо, що таке програма, але це просто статична структура дерева. Імовірно, ми хочемо, щоб наша програма фактично щось обчислила . Нам потрібна семантика.

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

Я не буду розглядати, як визначити формальну оперативну семантику (деталі трохи залучені), але в основному ми хочемо таких правил, як:

  1. num[n] є цінністю
  2. str[s] є цінністю
  3. Якщо num[n1]і num[n2]оцінити до цілих чисел n_1$ and $n_2$, thenплюс (num [n1], num [n2]) `оцінює ціле число $ n_1 + n_2 $.
  4. Якщо str[s1]і str[s2]оцінює рядки s1 і s2, то concat(str[s1], str[s2])оцінює рядок s1s2.

І т.д. Правила на практиці набагато формальніші, але ви отримуєте суть. Однак ми незабаром стикаємося з проблемою. Що відбувається, коли ми пишемо наступне:

concat(num[5], str[hello])

Гм. Це досить загадка. Ми ніде не визначили правило, як поєднати число з рядком. Ми могли б спробувати створити таке правило, але ми інтуїтивно знаємо, що ця операція є безглуздою. Ми не хочемо, щоб ця програма була дійсною. І таким чином нас невблаганно ведуть до типів.

Типи

Програма - це дерево, визначене граматикою мови. Програми мають значення за правилами виконання. Але деякі програми неможливо виконати; тобто деякі програми безглузді . Ці програми неправильно набрані. Таким чином, введення тексту характеризує змістовні програми мовою. Якщо програма добре набрана, ми можемо її виконати.

Наведемо кілька прикладів. Знову ж таки, як і з правилами оцінювання, я неформально представлю правила набору тексту, але їх можна зробити суворими. Ось кілька правил:

  1. Маркер форми num[n]має тип nat.
  2. Маркер форми str[s]має тип str.
  3. Якщо вираз e1має тип, natа вираз e2має тип nat, то вираз plus(e1, e2)має тип nat.
  4. Якщо вираз e1має тип, strа вираз e2має тип str, то вираз concat(e1, e2)має тип str.

Таким чином, згідно з цими правилами, існує plus(num[5], num[2])тип has nat, але ми не можемо призначити тип plus(num[5], str["hello"]). Ми говоримо, що програма (або вираз) добре набрана, якщо ми можемо призначити її будь-якого типу, і вона неправильно введена в іншому випадку. Система типу є здоровою, якщо можна виконати всі добре набрані програми. Haskell - звук; С - ні.

Висновок

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


4
+1. Найбільша хитрість, яку любителі динамічного набору тексту коли-небудь втягували, - це переконання світу, що ви можете мати "типи" без типової системи. :-)
ruakh

1
Оскільки ви не можете автоматично перевірити що-небудь цікаве для довільних програм, кожна система типу повинна надавати оператору передачі (або моральний еквівалент), інакше вона жертвує повнотою Тюрінга. Сюди входить , звичайно, і Haskell .
Кевін

1
@Kevin Я добре знаю теорему Райса, але це не так актуально, як ви могли б зробити. Для початку велика більшість програм не потребує необмеженої рекурсії. Якщо ми працюємо мовою, яка має лише примітивні рекурсії, наприклад, система Godel's T, ми можемо перевірити цікаві властивості за допомогою системи типів, включаючи зупинку. Більшість програм у реальному світі досить прості - я не можу подумати про те, коли я востаннє потребував кастингу. Тюрінг повноти завищений.
садок

9
"Динамічне набирання тексту насправді не друкується" мені завжди здавалося, як класичні музиканти, які говорять "Поп-музика насправді не музика", або євангелісти, які говорять, що "католики насправді не християни". Так, системи статичного типу є потужними та захоплюючими та важливими, а динамічне введення тексту - це щось інше. Але (як описано в інших відповідях) існує цілий ряд корисних речей поза системами статичного типу, які традиційно називаються набором тексту, і всі вони мають спільне спільне. Чому потрібно наполягати на нашому типу введення тексту як єдиному вірному наборі тексту?
Пітер ЛеФану Лумсдейн

5
@IMSoP: для чогось коротшого, ніж книги, нарис Кріса Сміта. Що потрібно знати, перш ніж обговорювати системи типів , чудово, визначаючи, чому динамічне введення дійсно зовсім інше, ніж статичне введення тексту.
Пітер ЛеФану Ламсдейн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.