From a930c0673dacef7d372b3d30654179b82101d7d0 Mon Sep 17 00:00:00 2001 From: klapaucius Date: Thu, 30 Oct 2025 21:46:42 +0500 Subject: [PATCH] sept. upd. --- hopes.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/hopes.md b/hopes.md index 00fa5d1..0f36736 100644 --- a/hopes.md +++ b/hopes.md @@ -33,6 +33,7 @@ - [Отец с атомным сердцем](#отец-с-атомным-сердцем) - [Big in Japan](#big-in-japan) - [Успели забыть о Прологе больше, чем японцы успели узнать](#успели-забыть-о-прологе-больше-чем-японцы-успели-узнать) + - [Новая надежда](#новая-надежда) - [Литература](#литература) @@ -1117,11 +1118,133 @@ ICL построила три прототипа ALICE. Первый прото У новой машины Flagship, которую разрабатывали в университете Манчестера и собирались построить в ICL к 88-му году, другая архитектура. В Flagship нет разделения на блоки памяти и вычислительные. У каждого вычислительного блока мегабайты памяти, к которой он имеет более быстрый доступ, чем через сеть к памяти остальных вычислительных блоков. И эксперименты с симулятором показали, что можно добиться 90% обращений к памяти в том же вычислительном блоке вообще без создания нагрузки на сеть для соединения блоков. И вычислительные блоки делались на процессорах MC68020. Пусть не британских, зато быстро работающих. Но для нашей истории, конечно, важнее не эти машины, а что машинистами было сделано полезного для имплементаций на обычном железе. +### Новая надежда + +Flagship был частью британского ответа на планы японцев по построению Пролог-машин. Но главным языком программирования этого проекта стал не Пролог, а HOPE. +Не единственным. Работали над имплементациями на Flagship-машине и других языков, в том числе и Пролога. Но главным - на котором должно был быть написано системное ПО - выбрали HOPE. +Причиной того, что выбрали HOPE, а не Пролог называют [Kean94] то, что в Имперском Колледже Лондона группа Дарлингтона уже занималась имплементацией HOPE и просто продолжила делать то, что уже делала. Что было вполне обычной реакцией на японский проект. Но Имперский Колледж был и важным центром по работе над Прологом. Ковальский из Эдинбурга отправился работать как раз туда. +Трудно сказать насколько на выбор языка повлияли технические аргументы, а не какие-то административные маневры, но аргументы были. +Во-первых, Пролог из за красных катов и императивных "предикатов" - менее "декларативный" язык, чем чисто функциональный ФЯ. Программисту на Прологе поэтому нужно больше думать о процедурной семантике. +Проблема этого аргумента в том, что те же претензии можно предъявить и к реально существующим в это время функциональным языкам. Как мы помним, эдинбургский HOPE только называется чисто функциональным, в реальном коде используют функции с побочными эффектами, написанными на POP-2. Как решать практические проблемы вроде ввода-вывода не нарушая чистоту языка пока не придумали. +К истории того как эти проблемы решали в ФЯ и некоторых логических языках мы вернемся в следующей части. +Следующим преимуществом ФЯ называют то, что ФЯ с хорошей производительностью имплементировать легче, чем Пролог. Что звучит правдоподобно, но как мы выяснили в нулевой части нашей истории, имплементацию Пролога с хорошей производительностью удалось сделать раньше, чем такую имплементацию языка, похожего на HOPE. +С остальными аргументами поспорить значительно труднее: в HOPE есть типы и функции высшего порядка, а в Прологе их нет. +Уоррен, правда, убеждал, что конструкции высшего порядка в Прологе и не нужны. Но убеждал не очень успешно в описываемое время. Сегодня мы знаем, что он победил и Пролог остался Прологом. Но в 80-е появились планы по усовершенствованию Пролога примерно таким же образом, каким в это время усовершенствовали ФЯ. +Когда-то типов и ФВП не было и в NPL и Пролого-образные языки позднее расширят и типами и ФВП. Но, по видимому, слишком поздно. О HOPE-фикации Пролога мы расскажем подробнее в другой главе. +Роль основного языка принесла и новые вызовы. Эдинбургский HOPE, E-HOPE, как его называли в Лондоне - ФЯ не самый практичный. И его эдинбургский интерпретатор - тем более. +И решение этой проблемы нельзя откладывать до появления HOPE-машины. Нужна быстрая имплементация для обычных машин. Потому, что нужно писать код еще до того, как первый прототип специальной машины будет готов. +На судьбоносном совещании в лаборатории Резерфорда - Эплтона Лондонская группа сообщала, что собирается написать более быстрый интерпретатор промежуточного языка, чем симулятор параллельного компьютера. +И можно бы было ожидать, что более практическая имплементация HOPE для обычных машин будет просто еще одним бэкендом для компилятора в инструкции параллельной машины. Который транслирует из того же промежуточного языка. Со временем такой компилятор действительно появился. Но только со временем. +Сначала в Лондоне написали один за другим два компилятора HOPE для разработки на обычных машинах, которые имели мало общего с компиляторами для параллельных машин. В самом большом проекте британской программы по созданию компьютера пятого поколения такое могли себе позволить. Развитие событий практически неизбежное потому, что этот самый промежуточный язык для новой специальной машины разрабатывался не в Лондоне и даже не в рамках того же проекта. Даже сегодня разработчики могли бы выбрать что-то внутреннее, не отягощенное координацией с другим проектом. Что уж говорить о временах бумажной корреспонденции и посылок с магнитной лентой. +Нежелание использовать результаты этого параллельного проекта оправдалось, промежуточный язык не был готов к тому времени, когда Лондонской группе Дарлингтона уже нужно было начинать писать ПО на HOPE. +Первый компилятор - IC HOPE для VAX-11 написал Энтони Филд (Antony Field) [Fiel88] [Perr91], имплементировав виртуальную машину под названием FPM (Functional Programming Machine). Есть ссылки на недошедший до нас университетский отчет 85-го года о нем. +Имплементаторы HOPE противопоставляют FPM остальным функциональным виртуальным машинам и утверждают [Perr91], что с имплементациями обычных языков программирования вроде Algol 60 у FPM больше общего. Спорное утверждение. Может и справедливо в случае G-машины или CAM, но FPM довольно похожа на FAM Карделли или имплементацию Poly (ML). +FPM - это очередная практичная версия SECD с поддержкой замыканий и оптимизация хвостовых вызовов. С копирующим сборщиком с фиксированным размером кучи. Там типы данных - обычно объекты кучи с тегами, но есть пары без поля для тега. И целые числа не являются объектами в куче вовсе, отличаются от указателей с помощью двухбитных тегов. Все это гораздо ближе к FAM, чем даже к самым смелым мечтам о функциональном Алголе 68, что уж говорить об Алголе 60. +Существенное отличие от FAM только в том, что в FPM отсутствуют оптимизации для каррирования. Это объяснимо, объявления функций в HOPE (пока что) не декларируют каррированные по умолчанию функции. +И IC-HOPE похож на компилятор Карделли. Операции ВМ разворачиваются макросами. И производительность генерируемого кода вычисления чисел Фибоначчи получилась побыстрее LML, но помедленнее, чем SML/NJ. Как и у компилятора Карделли. +Хорошо измерить производительность, правда, не успели. Первый компилятор быстро устарел, потеряв актуальность вместе с VAX-11. На смену этому компилятору для VAX вскоре пришел следующий компилятор, для MC68K. +Этот компилятор написали [Perr91] Найджел Перри (Nigel Perry) и Кейт Сефтон (Keith Sephton). Рантайм был доработан и куча теперь могла расти во время исполнения. Генерируемый код стал заметно быстрее. +Имперский Колледж Лондона распространял этот компилятор, анонс появился в рассылках в декабре 88-го года. +Переход на более перспективную платформу - не единственная причина для развития компилятора. Проблему практичности Эдинбургского HOPE не решить одной только быстрой имплементацией. Нужны изменения в самом языке. +Интересно, что с развитием HOPE сложилась ситуация, симметричная ситуации с развитием ML. Ядро разработчиков HOPE в Эдинбурге не особенно заботилось о похожести в деталях и забросило HOPE, начав проектирование Standard NPL. Извините, Standard ML. Периферийная группа разработчиков в Лондоне заботилась о сохранении детального сходства с HOPE гораздо сильнее, как и в случае с ML и INRIA. +Но в случае HOPE это более объяснимо, чем в случае ML. Эдинбургские разработчики NPL, HOPE и SML никогда особенно не заботились о деталях. И каждая версия, которых было множество, требовала бы править практически каждую строку кода. Если бы он был. Это кардинально отличается от LCF/ML, который не менялся долгие годы. +И стремление группы Дарлингтона изменять HOPE меньше не было полностью добровольным. У того, что HOPE стал основным языком флагманского проекта директората Алви, были не только полезные для его практичности последствия. Оказалось, что раз уж на заседаниях комитетов и комиссий договорились имплементировать HOPE, то нужно имплементировать HOPE а не какой-нибудь SML. Не совсем понятно какие отклонения от HOPE группа Дарлингтона могла себе позволить, но какие-то могла. Если и не HOPE 2, то по крайней мере HOPE+. + И второй компилятор имплементировал этот HOPE+. +Некоторые изменения в HOPE+ по сравнению с HOPE были сделаны для решения тех же проблем и решения были теми же, что в SML. В HOPE+, как и в SML, добавили [Darl89] [Robe89] целые числа со знаком и числа с плавающей точкой, массивы и стандартные 8-битные символы. +Судя по "категорному" коду, про который мы рассказывали в нулевой части, немногочисленные программисты на HOPE любили писать много локальных функций не требующих сигнатур с указанием типов. В отличие от тех, что на топлевеле. Так что в HOPE+ написание таких функций сделали удобнее, разрешив в `let` и `where` рекурсию. +Некоторые решения, хоть и были похожими - все же отличались. В HOPE планировали добавить исключения и их добавили и в SML и в HOPE+, но это были разные разновидности исключений. Чтоб не нарушить чистоту языка в HOPE+ сделали значения-ошибки, населяющие каждый ссылочный тип. +В новом HOPE (пока) не сделали функции каррированными по умолчанию, но в функциональном языке удобное частичное применение желательно, так что оно все равно было добавлено. Добавлено, как и в SML, но не такое как в SML. В новом HOPE можно было писать `f(?,x,?)` что соответствовало такой вот лямбде `lambda (a, b) => f(a, x, b)`. +Но некоторые выводы, которые сделали из опыта применения HOPE в Эдинбурге существенно отличались от выводов сделанных в Лондоне. +Опыт имплементации перегрузки в HOPE не считался особенно удачным, в основном из-за сложного и медленного алгоритма. В Эдинбурге не отказались от перегрузки полностью, как в свое время в LCF/ML. Но в SML она осталась для ограниченного набора операций. В новом HOPE перегрузка для пользовательских функций осталась, но имплементированная с помощью более быстрого алгоритма и несколько иначе. Старое поведение перегрузки не было определено ничем кроме эдинбургской POP-2 имплементации и не было воспроизведено полностью. +В SML отказались от паттерн-матчинга независящего от последовательности уравнений, который считали важным разработчики языков алгебраической спецификации. В Лондоне не порвали с этим алгебраическим прошлым и последовательность уравнений не стала важной как стала важной в SML, Прологе и языках Тернера. Но программисты хотели писать ПМ с пересекающимися паттернами, так что для HOPE+ нашли более-менее понятную систему определения того, какое сопоставление с образцом более точное [Perr91]. +Сопоставление паттернов-констант - более точное, чем сопоставление с переменной. Так что при применении функции + +``` +--- f(1, y) <= y; (a) +--- f(x, 2) <= x; (b) +--- f(a, b) <= a * b; (c) +``` + +так `f(1,3)` будет выбрано уравнение (a), в случае `f(5,2)` уравнение (b), в случае `f(3,4)` уравнение (c), а применение `f(1,2)` вызовет ошибку во время исполнения потому, что ни один из вариантов (a) и (b) не подходит лучше другого. Компилятор предупреждал о возможности такого исхода во время компиляции. +Эдинбургской группе разработчиков HOPE не пригодилась ленивость и в SML не попали ленивые списки из HOPE. Лондонская группа посчитала ленивость полезной, так что в HOPE+ все конструкторы стали ленивыми. Правда, функции все равно строгие, каждый параметр вычисляется до первого конструктора. +Это сочетание сегодня выглядит довольно необычно. И противоположно популярным рекомендациям писать на Haskell ленивые функции и типы данных со строгими полями. +В другом HOPE+ можно было добиться более привычного в наше время поведения. В другом HOPE+? +Между компиляторами HOPE для обычных машин и машин параллельных было мало общего. Разумеется, это привело к тому, что они имплементировали разные языки. +В параллельном HOPE+ были аннотации ленивости [Glyn90] и можно было форсировать "позвоночник" структуры данных без форсирования элементов: + +``` +dec length : !# ST SN #! list alpha -> num; +``` + +Или вычислить всю структуру: + +``` +dec sum : !# ST IN #! list num -> num; +``` + +А можно было и сделать функции ленивыми: + +``` +dec append : !# ST(WH,UN) #! (list alpha # list alpha) -> list alpha; +``` + +Здесь `WH` - аннотация поведения по умолчанию, вычисления до первого конструктора. А `UN` - означает ленивый аргумент. Так что параллельный HOPE+, пусть и с помощью аннотаций, но мог быть более обычным в наше время ленивым языком. +Практически до самого конца проекта в параллельном HOPE+ был [Robe89] и более привычный для нас сегодня паттерн-матчинг. Паттерны могли пересекаться и результат сопоставления зависел от последовательности уравнений. Прочие отличия были менее интересными недоработками. Взаимная рекурсия в `let` и `where` и числа с плавающей точкой не были имплементированы. +Отличий вариантов HOPE+ от HOPE не достаточно, чтоб наш обычный пример выглядел существенно иначе: + +``` +infixr :: : 5; +data list alpha == nil ++ alpha :: list alpha; + +dec map : (alpha -> beta) # list alpha -> list beta; +--- map(f, nil) <= nil; +--- map(f, x::xs) <= f x::map(f, xs); + +map(lambda x => x+y,[1,2,3]) where y == 1 end; +``` + +Он мог бы быть полностью идентичным, но мы не ставили перед собой такой цели. +Для тех, кто не был убежден в ненужности Пролога Лондонские разработчики HOPE планировали логические расширения. И даже имплементировали, хоть и не в основном, рабочем компиляторе. +Возможно, делать "функции" со многими результатами по умолчанию - не самая хорошая идея. Но почему бы не добавить в язык специальную нотацию для этого? Такая нотация - ЦФ-выражения уже была в языках Тернера и в NPL. И планировалась для HOPE, но долгое время продолжала только планироваться. + +``` +filter(p,xs) <= {x | x in xs : p x} +``` + +Правда, ЦФ-выражения, list comprehensions - не встроенный Пролог, а скорее какой-то из анти-Прологов Сассмана и Хьюита. Но что если встроить именно Пролог? + +``` +{(l1, l2) with l1, l2 | l1 <> l2 = [1, 2]} +{([], [1, 2]), ([1], [2]), ([1, 2], [])} : set(list num # list num) +``` + +Теперь функции можно применять слева от `=` как в более выразительных языках алгебраической спецификации. Но пока что только внутри новых "абсолютных абстракций множеств" [Darl87] [Darl89]. +Существует ли список из двух элементов? + +``` +{l with l | length l = 2} +``` + +Да! + +``` +{u :: (v :: nil)} : set(list alpha) +``` + +В функциональных языках Эдинбургской исследовательской программы такие расширения не прижились. Они сыграли более заметную роль в HOPE-фикации Пролога. Но это уже другая история. + ПРОДОЛЖЕНИЕ СЛЕДУЕТ Литература ========== +[Darl87]: Darlington, J. (1987) Software development using functional programming languages. ICL Technical J., 5 (3): 492-508 +[Glyn90]: Kewley, John M., and Kevin Glynn. "Evaluation annotations for Hope+." In Functional Programming: Proceedings of the 1989 Glasgow Workshop 21–23 August 1989, Fraserburgh, Scotland, pp. 329-337. London: Springer London, 1990. doi:10.1007/978-1-4471-3166-3_22 +[Robe89]: Robertson, I.B., Way, Wenlock. "Hope+ on Flagship." In Functional Programming: Proceedings of the 1989 Glasgow Workshop, 21-23 August 1989, Fraserburgh, Scotland, p. 296. Springer, 1990. doi:10.1007/978-1-4471-3166-3_20 +[Darl89]: Darlington, J. et al. (1989). A Functional Programming environment supporting execution, partial execution and transformation. In: Odijk, E., Rem, M., Syre, JC. (eds) PARLE '89 Parallel Architectures and Languages Europe. PARLE 1989. Lecture Notes in Computer Science, vol 365. Springer, Berlin, Heidelberg. doi:10.1007/3540512845_46 +[Perr91]: Perry, Nigel. "The implementation of practical functional programming languages." PhD diss., Department of Computing, Imperial College, 1991. +[Fiel88]: Field, Antony and Peter G. Harrison. “Functional Programming.” (1988). +[Kean94]: Keane, John A. "An overview of the Flagship system." Journal of Functional Programming 4, no. 1 (1994): 19-45. [Acce86]: Accetta, Mike, Robert Baron, William Bolosky, David Golub, Richard Rashid, Avadis Tevanian, and Michael Young. "Mach: A new kernel foundation for UNIX development." (1986): 93-112. [Alle78]: John Allen. 1978. Anatomy of LISP. McGraw-Hill, Inc., USA. [Alle2005]: John Allen. History, Mystery, and Ballast https://international-lisp-conference.org/2005/media/allen-slides.pdf https://international-lisp-conference.org/2005/media/allen-audio.mp3