Чи сумісна ета-еквівалентність функцій з послідовною операцією Haskell?


14

Лема: якщо припустити, що у нас є ета-еквівалентність (\x -> ⊥) = ⊥ :: A -> B.

Доведення: ⊥ = (\x -> ⊥ x)ета-еквівалентністю та (\x -> ⊥ x) = (\x -> ⊥)зменшенням під лямбда.

Звіт Haskell 2010, розділ 6.2, визначає seqфункцію двома рівняннями:

seq :: a -> b -> b
seq ⊥ b = ⊥
seq ab = b, якщо a ≠ ⊥

Потім він стверджує, "Як наслідок, ⊥ не є тим самим, що \ x -> ⊥, оскільки seq можна використовувати для їх розрізнення."

Моє запитання: чи це насправді наслідок визначення seq?

seqМається на увазі неявний аргумент, який би був незаперечним, якби seq (\x -> ⊥) b = ⊥. Однак я не зміг довести, що таке seqби було непорушним. Мені здається, таке seqє одночасно монотонним та безперервним, що ставить його у сферу обчислення.

Алгоритм, який реалізує такі як сл може працювати, намагаючись знайти для деяких , xде f x ≠ ⊥, перераховуючи область fпочинаючи з ⊥. Хоча таке втілення, навіть якщо це можливо взагалі, стає досить волохатим, коли ми хочемо зробити seqполіморфним.

Чи є докази того, що не існує обчислювана , seqщо ідентифікує (\x -> ⊥)з ⊥ :: A -> B? Крім того , є деякі будівництва , seqщо робить ідентифікувати (\x -> ⊥)з ⊥ :: A -> B?

Відповіді:


6

Спочатку давайте будемо чітко про те, чим seqвідрізняється від λ x . :λx.

bottom :: a
bottom = bottom

eta :: a -> b
eta x = bottom

-- This terminates
fortytwo = seq eta 42

-- This does not terminate
infinity = seq bottom 42

Тому експериментальний факт, що в Хаскеллі і λ x . оперативно відрізняються. Це також факт, і цілком очевидний, який обчислюється, оскільки Haskell обчислює його. Стільки про Haskell. Ви запитуєте про дуже конкретні фрази документації Haskell. Я читав це як той, що повинен задовольнити два задані рівняння, але цих двох рівнянь недостатньо для визначення . Ось чому: я можу навести вам дві моделі (просто набраних) λ -рахунків, в яких обчислюється і задовольняє заданим рівнянням, але в одній із моделей і λ x . λx.seqseqseqλseqλx. погодьтеся, в той час як в іншому вони цього не роблять.

У простій доменно-теоретичній моделі, де вирази інтерпретуються в області безперервних функцій [ D E ], маємо = λ x . , очевидно. Візьміть ефективні домени Скотта або деякі такі, щоб зробити все обчислюваним. Визначити в такій моделі нескладно .λ[DE]=λx.seq

Ми також можемо мати модель -рахунку, в якій розрізняють і λ x . , і тоді, звичайно, η -правило не може виконати. Наприклад, ми можемо це зробити, інтерпретуючи функції в домені [ D E ] , тобто домен простору функцій з доданим додатковим дном. Тепер - ну, нижня частина [ D E ] , а λ x . - елемент трохи вище нього. Їх не можна відрізнити за допомогою програми, оскільки вони обидва оцінюютьλseqλx.η[DE][DE]λx. , незалежно від того, до чого ви їх застосовуєте (вонидорівнює рівню). Але ми маємояк карту між доменами, і це завжди відрізняє дно від усіх інших елементів.seq


1
Це експериментальний факт, що в GHC та / або Hugs ⊥ і λx.⊥. На щастя, Haskell не визначено реалізацією. Моє запитання свідчить про те, що Haskell недостатньо визначений щодо сл.
Рассел О'Коннор

Чи можете ви дати посилання на те, що ви маєте на увазі під "ефективними доменами Скотта" Імовірно, це не означає, що частковий порядок може бути вирішеним. Також STLC не є поліморфним, але Haskell є. Зазвичай Haskell інтерпретується в System F або в одному з його похідних. Як це впливає на ваш аргумент?
Рассел О'Коннор

Розділ 1.1.4 мого доктора наук. Дисертація andrej.com/thesis/thesis.pdf має коротке визначення ефективних доменів Скотта, і це фактично перший хіт Google, який є у вільному доступі.
Андрій Бауер

2
Якщо ви напишете доказ для мене, ви отримаєте реалізацію Haskell 98, де встановлено ета-правило, що дозволяє (foldr (\ ab -> fab) z xs) оптимізувати до (foldr fz xs), викликаючи збільшення асимптотичної продуктивності від O (n ^ 2) до O (n) (див. ghc.haskell.org/trac/ghc/ticket/7436 ). Більш переконливий спосіб дозволить оптимізувати функцію NewTypeWrapper в (NewTypeWrapper. F), не змушуючи її розширювати етапи, а також запобігати певним асимптотичним покаранням продуктивності, що вводяться в даний час newTypes в GHC (наприклад, у використанні foldr).
Рассел О'Коннор

1
Насправді, вам доведеться переконатися, що ваш компілятор завжди реалізує як . Тобто, ви можете спокуситись не завжди укладати контракти і так в принципі λ x . і були б "іноді помітними", дуже небезпечною ситуацією. Щоб переконатися, що це не так, вам потрібно здійснити розумний спосіб, який передбачає нерегулярне безліч процесів, кожен із яких застосовує вашу функцію до базового елемента. Якщо будь-який з процесів припиняється, то може продовжуватися. Було б цікаво подивитися, чи можемо ми робити це послідовно. Хм. λx.λx.seqseq
Андрій Бауер

2

Зауважте, що специфікація, seqяку ви цитуєте, не є її визначенням. Процитуйте звіт Хаскелла "Послідовність функцій визначається рівняннями : [і тоді ви отримаєте рівняння]".

Запропонований аргумент здається, що seq був би непорушним, якщо seq (\ x -> ⊥) b = ⊥.

Така поведінка порушила б специфікацію seq.

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

Чи є доказ того, що не існує обчислюваної послідовності, яка б ідентифікувала (\ x -> ⊥) з ⊥ :: A -> B?

Якщо seq' (\x -> ⊥) bможна подумати, що ми можемо застосувати перший параметр (який є функцією) до якогось значення, а потім отримати ⊥. Але seqніколи не можна ототожнювати перший параметр зі значенням функції (навіть якщо воно трапляється для деякого використання seq) через його параметричного поліморфного типу. Параметричність означає, що ми нічого не знаємо про параметри. Крім того, seqніколи не можна приймати вираз і вирішити "це ⊥?" (пор. проблема зупинки), seqможе лише спробувати її оцінити, і сама розходиться до ⊥.

Що seqполягає в тому, щоб оцінити перший параметр (не повністю, але в "слабкій голові нормальної форми" [1], тобто в самому верхньому конструкторі), а потім повернути другий параметр. Якщо перший параметр трапляється (тобто не закінчується обчислення), то його оцінка призводить seqдо неприпинення, і таким чином seq ⊥ a = ⊥.

[1] Вільні теореми в присутності послідовності - Йоганн, Войттландер http://www.iai.uni-bonn.de/~jv/p76-voigtlaender.pdf


Специфікація, яку я даю для seq, є визначенням seq, тому що саме так йдеться у звіті Haskell 2010 у розділі 6.2. Визначення функції seq не підтримується у звіті Haskell 2010: слова "головна нормальна форма" зустрічаються лише один раз у звіті у абсолютно іншому контексті. Це також суперечить моєму розумінню, що GHC часто скорочує другий аргумент до послідовності перед першим аргументом, або перший аргумент взагалі не буде зменшений, оскільки аналізатор суворості довів, що він статично невисокий.
Рассел О'Коннор

Параметричність прямо не говорить про те, що ми не можемо застосувати будь-які деконструктори, а також не може ідентифікувати перший параметр зі значенням функції. Усі параметриcity говорять про поліморфне обчислення лямбда з фіксованими точками - це те, що seq може поглинати суворі функції, або, загалом, певні суворі відносини, що стосуються термінів, містять seq. Я визнаю, правдоподібно, що параметричність може бути використана для доведення (\ x -> ⊥) & ne; ⊥, але я хотів би бачити суворий доказ.
Рассел О'Коннор

У випадку функції f : forall a . a -> T(де Tє якийсь інший тип), тоді fне можна застосувати жодних деконструкторів до першого аргументу, оскільки він не знає, які деконструктори застосувати. Ми не можемо зробити "кейс" на типи. Я намагався вдосконалити вищевказану відповідь (включаючи цитування інформації про seqоцінку, щоб очолити нормальну форму).
dorchard

Я можу спробувати зробити суворий доказ пізніше, якщо знайду час (використання відносин у стилі Рейнольдса може бути хорошим підходом).
dorchard

@ RussellO'Connor: опис послідовності не "суперечить" тій поведінці, це лише оперативна специфікація (а поведінка - це оптимізація, яка не змінює кінцевий результат).
Blaisorblade

2

λx.λx.

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


1
Мабуть, ці деталі визначаються лише шляхом дезагартування в "ядро Haskell". Де це визначено? У звіті йдеться у розділі гл. 1.2 : "Хоча ядро ​​формально не визначено, воно є, по суті, злегка зафіксованим варіантом обчислення лямбда з прямою денотаційною семантикою. Переклад кожної синтаксичної структури в ядро ​​подається під час введення синтаксису."
Blaisorblade

Звіт Haskell 2010 говорить те саме , дивним чином.
Blaisorblade

Дякую за посилання на Абрамського! Я продемонстрував це, щоб побачити, як він відповідає на питання, і придумав таку відповідь: cstheory.stackexchange.com/a/21732/989
Blaisorblade

2

Доведення, що λ x. Ω ‌ ≠ Ω в - одна з цілей, яку Абрамський ставить для своєї лінивої теорії обчислення лямбда (стор. 2 його статті , яку вже цитував Удей Редді), оскільки вони обидва в нормальній формі слабкої голови. Щодо визначення 2.7, він чітко обговорює, що ета-зменшення λ x. M x → M, як правило, не вірно, але можливо, якщо M припиняється в будь-якому середовищі. Це не означає, що M має бути тотальною функцією - лише те, що оцінювання M повинно бути припинене (наприклад, зменшившись до лямбда).

Здається, ваше запитання мотивоване практичними проблемами (ефективністю). Однак, хоч звіт Haskell може бути менш ніж абсолютно зрозумілим, я сумніваюся, що рівняння λ x. ‌ «з» може принести корисну реалізацію Haskell; чи реалізує він Haskell '98 чи ні, є дискусійним, але, враховуючи зауваження, зрозуміло, що автори мали намір це зробити саме так.

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

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

import Control.Monad.ST
import Data.STRef
import Data.Maybe

produce_maybe_a :: Maybe a
produce_maybe_a = runST $ do { cell <- newSTRef Nothing; (\x -> writeSTRef cell (Just x) >> return x) `seq` (readSTRef cell) }

break_parametricity :: a
break_parametricity = fromJust produce_maybe_a

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

EDIT:

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

Оцінка (\x -> writeSTRef cell (Just x) >> return x)на випадкових входах не виконує запис у комірку. Лише команди ST, які входять до переданого послідовності runST, завжди виконуються. Аналогічно, біг main = (putStrLn "Hello") `seq` (return ())нічого не друкує на дисплей.
Рассел О'Коннор

@ RussellO'Connor, звичайно, ти маєш рацію - тестування важке, оскільки seq не має поведінки, про яку ми обговорюємо. Але я все ж думаю, що генеруючі елементи самі по собі порушують параметричність. Я спробую виправити відповідь, щоб пояснити це.
Blaisorblade

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