Зв'язок між контрактами та залежним типізацією


31

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

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

З цим, мабуть, спостерігається значна кількість перекриттів, і моя категоризація контрактів і залежних типів починає зникати.

Чи є щось глибше в будь-яких поняттях, які мені відсутні? Або це справді просто нечіткі категорії, що представляють одну і ту ж основну концепцію?

Відповіді:


26

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

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

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

Ці два погляди неоднакові, але вони пов'язані між собою. По суті, справа в тому, що з контрактами ми починаємо з універсальної області цінностей і використовуємо контракти для скорочення речей. Але коли ми використовуємо типи, ми намагаємося вказати менші домени значень (з бажаною властивістю) наперед. Таким чином, ми можемо з'єднати ці двоє за допомогою типів родинних відносин (тобто логічних відносин). Наприклад, див. Нещодавнє "Вину за всіх" Ахмеда, Findler, Сіка та Вадлера або "Значення типів: від внутрішньої до зовнішньої семантики" Рейнольдса .


Чому, на вашу думку, договори не містять кількісних показників?
Раду ГРИГо

3
Оскільки загалом не можна використовувати тести для встановлення універсально кількісно визначених властивостей функцій, це все.
Neel Krishnaswami

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

2
@Radu: Я називаю такі речі, як JML & co, "логіка програми". Мови затвердження логіки програм не обмежуються лише термінами з мови програм. Це дозволяє виключати речі, такі як твердження, що не припиняються, або побічні результати, які не мають приємної логічної інтерпретації. (Однак такі речі мають значення для перевірки контрактів - див. Нещодавню роботу Пучелла та Това в ESOP щодо використання державних, імперативних контрактів для відстеження лінійних властивостей.)
Ніл Кришнасвамі

2
Це тому, що я ввів в оману прізвище Това. Див. "Державні договори на афінські
Neel

13

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

Тим не менш, факт відсутності алгоритму перевірки контрактів (який завжди працює) не означає, що майже немає алгоритмів перевірки контрактів (які, як правило, працюють на практиці). Я рекомендую вам переглянути Spec # та плагін Jessie від Frama-C . Вони обидва працюють, висловлюючи "ця програма підкоряється цьому договору", як висловлення в логіці першого порядку за допомогою генерації умови перевірки , а потім запитуючи SMTвирішити, спробувати знайти доказ. Якщо розв'язувальник не знайде доказ, то або програма неправильна, або ж, вирішувач не зміг знайти підтвердження, яке існує. (Ось чому це "майже" алгоритм перевірки контрактів.) Існують також інструменти, засновані на символічному виконанні, що означає, що "ця програма підкоряється цьому договору" виражається як купа пропозицій (за деякою логікою). Див., Наприклад, jStar .

Робота Фланагана намагається взяти те, що найкраще з обох світів, так що ви можете швидко перевірити типові властивості, а потім працювати на відпочинок. Я не дуже знайомий з гібридними типами, але я пам’ятаю, як автор говорив, що його мотивація полягала в тому, щоб розробити рішення, яке потребує меншої кількості анотацій (ніж його попередня робота над ESC / Java). У певному сенсі, однак, існує певна інтеграція між типами та контрактами в ESC / Java (і Spec #): під час перевірки контрактів вирішувач повідомляє, що перевірка типу успішна, щоб вона могла отримати цю інформацію.


7

Контракти можна перевірити статично. Якщо ви подивитесь на стару роботу Дани Сю над ESC / Haskell , вона змогла здійснити повну перевірку контрактів під час компіляції, покладаючись лише на доказ теореми для арифметики. Припинення вирішується простим обмеженням глибини, якщо я пам'ятаю правильно:


6

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

Залежні типи дозволяють кодувати дуже широкий спектр властивостей у системі типів, типи властивостей, які очікують програмісти-контрактори. Це тому, що вони можуть залежати від значень типу. Залежні типи мають тенденцію статично перевірятися, хоча я вважаю, що цитовані вами документи дивляться на альтернативні підходи.

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


Трохи оманливо сказати, що анотації у стилі Хоара можна перевірити статично. Якщо логіка FO, як це зазвичай, то проблема, безумовно, не може бути вирішена. Але так, я знаю, ти мав на увазі, що можна спробувати і навіть досягти успіху у багатьох ситуаціях.
Раду ГРИГо

1
У мене було враження, що отримання доказів може бути невідрізним, але перевірка доказу повинна бути. Багато мов, що залежать від типу, покладаються на користувача, щоб надати доказове значення кількості типів теореми.
Джейсон Райх

Ти правий. Але я живу в автоматизованому світі, де користувача, як правило, не вимагають доказів.
Раду ГРИГо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.