Чим імперативні мови більше відрізняються одна від одної, ніж функціональні мови?


17

Я читаю "Впровадження функціональних мов програмування" Саймона Пейтона Джонса, і є одна заява, яка мене трохи здивувала (на стор. 39):

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

Тепер це було написано в 1987 році, і на мої думки з цього приводу могли вплинути більш сучасні мови програмування, яких тоді не було і не було популярним. Однак мені це важко повірити. Наприклад, я думаю, що описана мова програмування Міранди (ранній попередник Haskell) має набагато більшу семантику порівняно зі суворою мовою, такою як ML, ніж, наприклад, C має Pascal або, можливо, навіть, C має smalltalk (хоча я поступлю це C ++ надає певну валідацію своєї точки :-).

Але знову ж таки, я базую це на своєму інтуїтивному розумінні. Чи в більшості своїй правильно сказати Саймон Пейтон Джонс, чи це суперечливий момент?

Відповіді:


19

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

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

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

Причина такої математичної складності полягає в тому, що нам потрібно вміти одночасно інтерпретувати параметричний поліморфізм та стан вищого порядку. Але як тільки ви це зробите, ви в основному не вдома, оскільки ця конструкція містить усі жорсткі шматочки. Тепер ви можете інтерпретувати типи ML та Haskell за допомогою звичайних монадичних перекладів. Суворий та ефективний простір функцій ML a -> bперекладається на право> , а лінивий простір функцій Хаскелла перекладається на , з монадичний тип побічних ефектів, що інтерпретують IO монаду Haskell, а є інтерпретацією типу ML або типу Haskell , іаТбабТ(А)аa - це показник у цій категорії PER.

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

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

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


10

Моє відчуття полягає в тому, що SPJ мав на увазі суто функціональні мови - тобто мови, які відносно прозорі. Це включає, наприклад, Haskell, Miranda, Clean, але не ML. Коли ви володієте суто функціональною мовою, загалом ви можете надати їй досить чисту і чітко визначену денотаційну семантику. Загалом ця семантика буде схожа на обчислення лямбда, з деякими перетвореннями тут і там. Як правило, у вас буде типова система, яка дегустує на щось, що нагадує варіант System F - можливо, більш потужне в деяких відношеннях, більш обмежене в інших. Ось чому вилучення коду до / компіляція в Haskell, O'Caml тощо є відносно простим від складних залежних від кореспондентів доказів, таких як Agda.

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

Заява Саймона також вписується у дуже важливий історичний контекст. На момент народження Хаскелла (1987 р.) Існувала сукупність не строгих функціональних мов - не лише Міранда, але Ледачий М.Л., Оруелл, Чистий та багато інших. Крім певних синтаксичних варіацій, всі вони були дуже однаковою мовою. Саме це було мотивацією для формування комітету Хаскелла. Докладніше про це див. У розділі "Історія Haskell: лінивий клас": http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/ .


5

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

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

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

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

Світогляд простір функціонального мовного дизайну просто більш специфічний і узгоджений, ніж простір "імперативного програмування", який об'єднує складання, C, Smalltalk, Forth та десятки інших докорінно різних мов в одну категорію catchall.


4

Я думаю, що цитата Саймона Піджена насправді є непомітним зауваженням.

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

Майже всі функціональні мови використовують управління зібраною сміттям та рекурсивні структури даних (за походженням від Lisp), більшість з них використовує "алгебраїчні" типи даних та відповідність шаблонів (походить від Надії), багато з них використовують функції вищого порядку та поліморфні функції ( зародився М.Л.). Крім того, консенсус зникає. Вони відрізняються від використовуваних модульних систем, способів обробки операцій із зміни стану та інших обчислювальних ефектів, порядку замовлення (call-by-name vs call-by-value) тощо.

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

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

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


Мені дурно цікаво, чому ви використовували цитати скарей у "алгебраїчних" типах даних?
Стівен Шоу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.