Skip to content

Commit 1883935

Browse files
author
Marat Zimnurov
committed
Монада получила форму: в монаде разворачивается в разбор до конца разбора
Пункт 3 плана. Полиморфизм сделал монаду выразимой ТИПОМ; здесь сделана ФОРМА — объявление `монада`, блок `в монаде`, доказательство устройства и проверка трёх законов связывания на сетке. монада «Возможно» от «А» возврат «Обернуть» соединение «Сплющить» тотальная функция «Итог со скидкой» принимает номер: число возвращает «Возможно» от числа в монаде «Возможно» пусть цена равно «Цена позиции» от номер пусть скидка равно «Скидка по цене» от цена возврат цена минус скидка Обещание плана «функций первого класса ей не нужно, потому что тело известно синтаксически» выполнено буквально — и оказалось не самоочевидным. Связывание `связать(м, к) = соединение(отобразить(к, м))` требует, чтобы `к` было значением, а у продолжения есть свободные имена, которых тег не захватывает (частичного применения нет). Выход в том, что `к` НЕ СТРОИТСЯ: отображение эндофунктора печатается НА МЕСТЕ, разбором по вариантам типа, и тело стоит прямо в ветви. Замыкать нечего, потому что это выражение, а не функция. Отображение никто не объявляет: у полиномиального функтора законное отображение ровно одно, и компилятор выводит его из устройства типа. Поэтому строки `эндофунктор «Возможно»` из контракта здесь нет — она повторяла бы имя строкой выше и не проверяла ничего, — а функториальность ДОКАЗАНА построением. Разворачивание сделано внутри разбора, и это главное решение: наружу парсера форма не выходит вовсе. Печать во все восемь целей, анализ завершаемости и обе реализации самоприменения получили её даром — `self/parser.flang` и `self/types.flang` не потребовали НИ ОДНОЙ правки. В `self/lexer.flang` дописаны четыре поверхности в таблицу слов, потому что таблица сверяется тестом поверхность в поверхность; разбирать их лексеру не нужно, и он не разбирает — ровно как с `моноид`. Новых ключевых слов четыре: `монада`, `возврат`, `соединение`, `в монаде`. Голых вхождений в 133 исходниках — ноль, и проверено это не только `grep`-ом: все 133 файла размечены новым лексером, ни один новый идентификатор не сработал ни разу. Слово `вернуть` для строки-результата ОТВЕРГНУТО измерением — `пусть вернуть равно` стоит голым в examples/rosetta/towers-of-hanoi.flang; роль взял `возврат`, и это вышло лучше замены: `возврат «Обернуть»` называет η, `возврат выражение` её применяет. Граница проведена явно. ДОКАЗЫВАЕТСЯ сличением объявлений: тип параметричен, параметр у него есть, `возврат` ведёт из «А» в M«А», `соединение` из M(M«А») в M«А», параметр стоит в полях целиком, блок без `возврат` не собирается. ПРОВЕРЯЕТСЯ на конечной сетке из примеров автора: левая единица, правая единица, ассоциативность связывания — с контрпримером в сообщении, как у моноида. Три измерения про законы, ни одно не было ожидаемым: 1. у «Возможно» ассоциативность отдельно сломать НЕЛЬЗЯ — единицы задают `соединение` на всех трёх входах целиком, свободы не остаётся; 2. перепутанный порядок склейки у монады-писателя — НЕ ошибка: противоположный моноид тоже моноид, законы правы, а ловится это примером. Записано тестом, чтобы никто не «починил» проверку под ожидание; 3. значит ассоциативность ловит то, чего не ловят единицы, только на операции с нейтралью, но без ассоциативности. В тесте это `а плюс б плюс а·б·(а−б)`: ноль нейтрален точно, а перестановка скобок даёт 37 против 5. Второй дефект нашёл ЗАПУСК, а не проверка. Отображение пересобирает вариант целиком, значит соседние поля надо связать и подставить обратно; связывались они под своими же именами — и молча крали имена у автора. Функция с параметром `метка` над монадой с полем `метка` получала в теле блока метку из-под варианта: «ш7» вместо «снаружи7». Типы совпадали, поэтому проверка молчала; законы говорят о значениях, а не об именах, и тоже молчали бы. Отвергать такую программу было бы произволом — как называются поля ВНУТРИ монады, автор знать не обязан, — и переименовывается копия, а не программа: `метка`, `метка 2`, `метка 3`. Улика — два теста, столкнутые с обеих сторон. Первый дефект нашёлся раньше, и не в монаде. Программа-пример написана на ДВУХ монадах, вторая — на типе с двумя параметрами, по правилу из POLY.md («новая форма не проверена, пока на ней не написана настоящая программа»). Блок над ней не собирался: у конструктора «Успех» параметр «Значение» решается полем, а «Беда» — ничем, и ожидание, которое её знает, не доезжало — `callType`, `constructType` и `recordType` гасили его в null, как только тип аргумента или поля оказывался параметрическим. Починено тремя местами: ожидание участвует и ДО аргументов, но только как ПОДСКАЗКА вложенному выводу, в `matchAgainst` и `sameType` оно по-прежнему не входит. Отсюда свойство правки: принять она может больше прежнего, отвергнуть — ровно столько же. Мерено, а не оценено: AST всех 133 исходников репозитория напечатан до и после — расхождений 0; все 133 размечены новым лексером — новых ключевых слов сработало 0; self-types.test.mjs (46 тестов, включая порченые файлы и фаззинг) — зелёный, то есть правка вывода типов с `self/types.flang` не разошлась; flang/examples/monad/order-total.flang: 12 функций, ВСЕ доказаны тотальными, 27 примеров сходятся, обе монады проходят все три закона; печать во все восемь целей; C собран `cc -std=c99 -Wall -Wextra -Werror -pedantic` без предупреждений; сверка с интерпретатором: 48 точек на напечатанном C, 42 на напечатанном JS — расхождений 0; форма и написанный руками вложенный разбор дают одно и то же на 7 входах. Чего форма не может, и это записано уликой в claims.test.mjs: монадой не объявить список и всё рекурсивное, включая ввод-вывод. Монада ввода-вывода — `«Дело» от «А»` с продолжением полем `функция из «Отклик» в («Дело» от «А»)`, а отображение внутрь функции на месте не печатается. Значит машина продолжений из io.mjs на форму сегодня НЕ переезжает, вопреки тому, что обещал раздел «Чем это не монада»; обещание не отменяется, а получает верный срок — частичное применение, фаза 4 в HOF.md, а не полиморфизм, которого уже хватило.
1 parent f1c3ead commit 1883935

16 files changed

Lines changed: 2597 additions & 65 deletions

File tree

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,10 @@ would be nothing to check — equality of two computations is undecidable.
666666

667667
Where the surface stops is stated as plainly: category names (`из «Продажи» в «Биллинг»`) remain
668668
a note for the reader, because a category is not declared as an entity and there is nothing to
669-
check membership against. Natural transformations, monads, monoids and bifunctors are described
670-
in [`flang/cat/SPEC.md`](flang/cat/SPEC.md) and are not implemented.
669+
check membership against. Natural transformations are described in
670+
[`flang/cat/SPEC.md`](flang/cat/SPEC.md) and are not implemented; monoids, groups, isomorphisms,
671+
bifunctors and monads are — and a monad also comes with the binding form `в монаде`
672+
([`flang/cat/MONAD.md`](flang/cat/MONAD.md)).
671673

672674
---
673675

@@ -1113,10 +1115,13 @@ attaching a solver to the verification conditions is an open task, not a feature
11131115
diagnostic blames the pattern instead of naming the real cause. Workaround: rename it, or use
11141116
the explicit `случай вариант «Имя»` form the stdlib uses.
11151117

1116-
**The category surface.** Morphisms, composition, chains, identities and functors are
1117-
implemented. Natural transformations, monads, monoids, groups and bifunctors are specified in
1118-
[`flang/cat/SPEC.md`](flang/cat/SPEC.md) and are not. Category names in a functor declaration are
1119-
a note for the reader, not a checked claim.
1118+
**The category surface.** Morphisms, composition, chains, identities, functors, bifunctors,
1119+
isomorphisms, monoids, groups and monads are implemented; a monad also comes with the binding form
1120+
`в монаде`. Natural transformations are specified in [`flang/cat/SPEC.md`](flang/cat/SPEC.md) and
1121+
are not implemented. Category names in a functor declaration are a note for the reader, not a
1122+
checked claim. A list — and anything recursive, I/O included — cannot be declared a monad today:
1123+
the endofunctor map is printed in place, so the parameter must occupy a whole field
1124+
([`flang/cat/MONAD.md`](flang/cat/MONAD.md)).
11201125

11211126
**Concurrency.** Six steps of seven. The missing one is the sixth — a scheduler in the C runtime:
11221127
processes are printed only to Elixir, and the other seven targets turn a program with `процесс`

README.ru.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,10 @@ FLANG_COMPOSE_MISMATCH: композиция «оформить» не стык
677677

678678
Где поверхность кончается, сказано так же прямо: имена категорий (`из «Продажи» в «Биллинг»`)
679679
остаются пометкой для читателя, потому что категория отдельной сущностью не объявляется и
680-
проверять принадлежность не на чем. Естественные преобразования, монады, моноиды и бифункторы
681-
описаны в [`flang/cat/SPEC.md`](flang/cat/SPEC.md) и не реализованы.
680+
проверять принадлежность не на чем. Естественные преобразования описаны в
681+
[`flang/cat/SPEC.md`](flang/cat/SPEC.md) и не реализованы; моноиды, группы, изоморфизмы,
682+
бифункторы и монады — реализованы, и у монады заодно есть форма связывания `в монаде`
683+
([`flang/cat/MONAD.md`](flang/cat/MONAD.md)).
682684

683685
---
684686

@@ -1121,10 +1123,13 @@ node --test flang/test/core-json.test.mjs
11211123
диагностика винит образец вместо настоящей причины. Обходится переименованием либо явной формой
11221124
`случай вариант «Имя»`, которой пользуется стандартная библиотека.
11231125

1124-
**Категорная поверхность.** Морфизмы, композиция, цепочки, единицы и функторы реализованы.
1125-
Естественные преобразования, монады, моноиды, группы и бифункторы описаны в
1126-
[`flang/cat/SPEC.md`](flang/cat/SPEC.md) и не реализованы. Имена категорий в объявлении функтора —
1127-
пометка для читателя, а не проверяемое утверждение.
1126+
**Категорная поверхность.** Морфизмы, композиция, цепочки, единицы, функторы, бифункторы,
1127+
изоморфизмы, моноиды, группы и монады реализованы; у монады есть форма связывания `в монаде`.
1128+
Не реализованы естественные преобразования — они описаны в
1129+
[`flang/cat/SPEC.md`](flang/cat/SPEC.md). Имена категорий в объявлении функтора —
1130+
пометка для читателя, а не проверяемое утверждение. Монадой сегодня не объявить список и всё
1131+
рекурсивное, включая ввод-вывод: отображение эндофунктора печатается на месте, поэтому параметр
1132+
обязан стоять в поле целиком ([`flang/cat/MONAD.md`](flang/cat/MONAD.md)).
11281133

11291134
**Конкурентность.** Сделаны шесть шагов из семи. Не сделан шестой — планировщик в рантайме C:
11301135
процессы печатаются только в Elixir, а остальные семь целей дают из программы с `процесс`

docs/overview.ru.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,27 @@ FLANG_COMPOSE_MISMATCH: «выставить» приводит в «Счёт»,
119119
тела, вычислять нечего. Это допущение автора, и компилятор отвечает лишь на то,
120120
осмысленно ли оно сформулировано.
121121

122-
Естественные преобразования и монады описаны в контракте `flang/cat/SPEC.md` и
123-
не реализованы. Причина сместилась: раньше мешал сам параметрический
124-
полиморфизм, теперь он есть — и в языке, и в самоприменении, и в стандартной
125-
библиотеке. Мешает то, что `checkMorphisms` и `checkFunctors` знают имя типа, а
126-
не применение: домен морфизма ищется как `ctx.records.has(имя)`, а «из функтора
122+
Монада объявляется на параметрическом типе и называет две функции — `возврат`
123+
(η) и `соединение` (μ). Граница «доказано / проверено» проходит здесь так же,
124+
как у моноида: доказывается устройство — тип параметричен, `возврат` ведёт из
125+
«А» в M«А», `соединение` из M(M«А») в M«А», — а левая единица, правая единица и
126+
ассоциативность связывания проверяются на конечной сетке из примеров автора, с
127+
контрпримером в сообщении.
128+
129+
Отображение эндофунктора при этом не объявляется вовсе: у полиномиального
130+
функтора оно ровно одно, и компилятор выводит его из устройства типа. На том же
131+
стоит форма `в монаде` — do-нотация словами, где каждое `пусть` есть
132+
связывание, а последняя строка `возврат` есть η. Форма разворачивается
133+
компилятором ВНУТРИ разбора, в обычные вызовы поверх обычного `разбор`, поэтому
134+
печать во все восемь целей и оба слоя самоприменения получают её даром, а
135+
функций первого класса ей не требуется: тело продолжения известно
136+
синтаксически. Подробности и границы — `flang/cat/MONAD.md`.
137+
138+
Естественные преобразования описаны в контракте `flang/cat/SPEC.md` и не
139+
реализованы. Причина сместилась: раньше мешал сам параметрический полиморфизм,
140+
теперь он есть — и в языке, и в самоприменении, и в стандартной библиотеке.
141+
Мешает то, что `checkMorphisms` и `checkFunctors` знают имя типа, а не
142+
применение: домен морфизма ищется как `ctx.records.has(имя)`, а «из функтора
127143
«Список» в функтор «Возможно»» — утверждение про применения. Это фаза 3 в
128144
`flang/cat/POLY.md`.
129145

flang/PLAN.md

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,25 @@
8686
зависимость такой, какой она вышла:
8787

8888
```
89-
1. Параметрический полиморфизм ──→ 3. Монада ──→ 4. форма «в монаде» поверх готовой машины
89+
1. Параметрический полиморфизм ──→ 3. Монада и форма «в монаде»
9090
4. Ввод-вывод (машина продолжений) ✅ ──→ 6. Отказоустойчивость
9191
```
9292

93+
Стрелка «3 → 4» не пригодилась и во второй раз: форма `в монаде` сделана, а
94+
машина продолжений ввода-вывода на неё НЕ переехала. Причина измерена, а не
95+
предположена: монада ввода-вывода — это `«Дело» от «А»`, где продолжение стоит
96+
полем типа `функция из «Отклик» в («Дело» от «А»)`, а форма разворачивает только
97+
те типы, у которых параметр стоит в поле ЦЕЛИКОМ. Проверено программой:
98+
99+
```
100+
FLANG_MONAD монада «Дело»: в варианте «Дальше» параметр «А» стоит внутри поля
101+
«потом», а не целиком; отображение внутрь применения на месте
102+
не разворачивается
103+
```
104+
105+
Переезд ждёт частичного применения — фазы 4 в `HOF.md`, — и до тех пор
106+
написанное сегодня продолжает работать, как и обещал пункт 4.
107+
93108
**1. Параметрический полиморфизм. ✅ СДЕЛАН, включая самоприменение.** Пока его
94109
не было, `Возможно` для чисел и для строк были двумя типами с разными именами
95110
конструкторов, `M(M)` — третьим, написанным руками, монада не выражалась вовсе, а
@@ -183,12 +198,41 @@ gcc и clang, Java, Elixir, Rust, Python; Go и .NET на машине нет
183198
Осталось: прослеживание тегов по параметрам и частичное применение.
184199
Подробности и порядок — `flang/cat/HOF.md`.
185200

186-
**3. Монада и `в монаде`. 🟢 Разблокирована пунктом (1), форма ещё не сделана.**
187-
Требовала (1): монада — эндофунктор плюс два преобразования, а эндофунктор без
188-
параметра типа не выражался. Теперь выражается — тип, «Обернуть» и «Связать»
189-
проходят все три проверки. Осталась синтаксическая форма `в монаде`. Форма `в монаде`
190-
разворачивается компилятором в вызовы `возврат` и `соединение`; функций первого
191-
класса ей не нужно, потому что тело известно синтаксически.
201+
**3. Монада и `в монаде`. ✅ СДЕЛАНЫ.** Требовала (1): монада — эндофунктор плюс
202+
два преобразования, а эндофунктор без параметра типа не выражался. Теперь
203+
выражается, и на нём сделана форма.
204+
205+
Обещание «разворачивается компилятором в вызовы `возврат` и `соединение`;
206+
функций первого класса ей не нужно, потому что тело известно синтаксически»
207+
выполнено буквально — и оказалось не самоочевидным. Связывание требует, чтобы
208+
продолжение было ЗНАЧЕНИЕМ, а у продолжения есть свободные имена, которые тег
209+
захватить не умеет (частичного применения нет, `HOF.md`, фаза 4). Выход в том,
210+
что продолжение не строится вовсе: отображение эндофунктора печатается НА МЕСТЕ,
211+
`разбор`ом по вариантам типа, и тело стоит прямо в ветви. Свободные имена
212+
работают, потому что это выражение, а не функция.
213+
214+
Отображение при этом никто не объявляет — компилятор выводит его из устройства
215+
типа: у полиномиального функтора законное отображение ровно одно. Поэтому
216+
функториальность ДОКАЗАНА построением, а строки `эндофунктор` в объявлении нет.
217+
218+
Разворачивание сделано внутри разбора, поэтому наружу парсера форма не выходит:
219+
печать во все восемь целей, анализ завершаемости и обе реализации
220+
самоприменения получили её даром — `self/parser.flang` и `self/types.flang` не
221+
потребовали НИ ОДНОЙ правки, в `self/lexer.flang` дописаны только четыре
222+
поверхности в таблицу слов, потому что таблица сверяется тестом.
223+
224+
Новых ключевых слов четыре: `монада`, `возврат`, `соединение`, `в монаде`; голых
225+
вхождений в 133 исходниках — ноль, проверено разметкой новым лексером, а не
226+
только `grep`-ом. Слово `вернуть` отвергнуто измерением: оно стоит голым именем
227+
в `examples/rosetta/towers-of-hanoi.flang`.
228+
229+
Устройство доказывается сличением объявлений, три закона связывания
230+
проверяются на сетке из примеров автора с контрпримером в сообщении. По дороге
231+
нашёлся настоящий дефект — не в монаде, а в выводе типов: ожидание не доезжало
232+
внутрь аргумента вызова и внутрь поля конструктора, из-за чего блок над
233+
ДВУХпараметрической монадой не собирался. Починено тремя местами; сверка с
234+
`self/types.flang` на всём репозитории и на сломанных программах — расхождений
235+
ноль. Подробности, границы и три измерения про законы — `flang/cat/MONAD.md`.
192236

193237
**4. Ввод-вывод. 🟡 Сделан — но НЕ монадой.** Язык остался чистым: описание
194238
действия — обычное значение (`«Поручение»`, пять вариантов, набор закрыт), а

flang/SPEC.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,37 @@ flang, целиком лежащая в тотальном классе.** Об
176176
**стирается**: все восемь бэкендов уже печатают одно представление значения,
177177
и `«Возможно» от числа` со `«Возможно» от строки` дают одну фабрику варианта.
178178

179+
### Монада и форма `в монаде`
180+
181+
Монада объявляется НА параметрическом типе и называет две функции — η и μ.
182+
Отображение эндофунктора не объявляется: у полиномиального функтора оно ровно
183+
одно, и компилятор выводит его из устройства типа.
184+
185+
```flang
186+
монада «Возможно» от «А»
187+
возврат «Обернуть»
188+
соединение «Сплющить»
189+
190+
тотальная функция «Итог со скидкой»
191+
принимает номер: число
192+
возвращает «Возможно» от числа
193+
в монаде «Возможно»
194+
пусть цена равно «Цена позиции» от номер
195+
пусть скидка равно «Скидка по цене» от цена
196+
возврат цена минус скидка
197+
```
198+
199+
Каждое `пусть` — связывание, `возврат` — последняя строка блока. Форма
200+
**разворачивается компилятором внутри разбора** в вызовы объявленных `возврат`
201+
и `соединение` поверх `разбор` по вариантам типа, поэтому в AST её нет и все
202+
последующие слои — типы, завершаемость, восемь бэкендов, самоприменение — о ней
203+
не знают. Функций первого класса форме не нужно: тело продолжения известно
204+
синтаксически и печатается на месте, а не заворачивается в значение.
205+
206+
Устройство монады доказывается сличением объявлений, три закона связывания
207+
проверяются на конечной сетке. Подробности, счёт занятых слов и границы —
208+
`flang/cat/MONAD.md`.
209+
179210
## 4. Синтаксис
180211

181212
Отступный, без скобок — как в FTS. Русская и английская поверхности
@@ -398,6 +429,17 @@ Pattern := { "kind": "empty" } пустой с
398429
"initial": "Начать", "handler": "Дальше" }]
399430
```
400431

432+
### Монада
433+
434+
Объявление добавляет ещё один необязательный список верхнего уровня; форма
435+
`в монаде` в AST не появляется вовсе — к концу разбора она уже развёрнута в
436+
`call` и `match` (`flang/cat/MONAD.md`).
437+
438+
```jsonc
439+
"monads": [{ "kind": "monad", "name": "Возможно", "param": "А",
440+
"unit": "Обернуть", "join": "Сплющить" }]
441+
```
442+
401443
Программе, где встретилось имя из словаря ввода-вывода (или объявлен `план`),
402444
парсер приписывает три суммы — `«Поручение»`, `«Отклик»`, `«Продолжение»`
403445
(`flang/src/io.mjs`), по тому же правилу и по той же причине, что сумму

0 commit comments

Comments
 (0)