LINUX.ORG.RU

кто понимает ковариантность?

 , , , , ковариантность


0

3

Просмотрел три статьи про вариантность, во всех неточности или ошибки:

https://ru.wikipedia.org/wiki/Ковариантность_и_контравариантность_(программир...

Статья неверна в принципе, начиная с определений:

Ковариа?нтность и контравариа?нтность[1] в программировании — способы переноса наследования типов на производные[2] от них типы — контейнеры, обобщённые типы, делегаты и т. п.

Ковариантностью называется сохранение иерархии наследования исходных типов в производных типах в том же порядке.

Если мы просто передаём параметр, List<Cat> там, где от нас ждут List<T extends Animal>, то мы можем подставить List<Cat> «вместо» List<Animal>, но при этом List<Cat> не становится потомком List<Animal>. Т.е., иерархии никакой нет, а есть заменимость типов в конкретном контексте.

Далее, если мы просто пишем Animal *А = new Cat(), то я бы это тоже рассмотрел как ковариантность, хотя здесь нет никаких производных иерархий. Точно так же, здесь есть подстановка одного вместо другого, я бы назвал это «тривиальным» или «единичным» случаем вариантности. Хотя, конечно, о терминах не спорят - их просто принимают. Но если мы говорим о натуральных числах, то логичнее включить в определение единицу, а не начинать их с двойки.

http://habibutsu.github.io/variance.html - для С++ ошибка в том, что говорится «нужно было С», или «нужно было А», в то время как правильно будет «нужно было B или C» или «нужно было B или А»

http://boyarincev.net/2014/09/covariance-and-contrvariance-in-c-sharp/

В контравариантности путаница (неправильно объяснено).

И т.д.

Вопрос: где же найти правильную статью про ковариантность, но без теорката (из моих трёх статей одна - с теоркатом, но её это не спасло от фактических ошибок). И заодно, предлагаю своё определение:

**********************

Вариантность - это возможность использовать подтип Пт вместо супертипа Ст или наоборот, в ряде частных случаев:

  • в место, типизированное как Ст, можно записать Пт
  • в место, типизированное как функция(Пт), можно записать функцию типа функция(Ст). В место, типизированное как функция() — Ст, можно записать функцию типа функция() — Пт
  • если типизированный контейнер Конт<T> только читается из места, типизированного как Конт<Ст>, то можно записать в него Конт<Пт> (в C# и в Java такая возможность замены требует особого указания в сигнатуре места). Если в него только пишется, то в место, типизированное как Конт<Пт>, можно записать Конт<Пт>
  • если виртуальная функция принимает Пт, то её можно перекрыть в потомке так, что она будет принимать Ст. Если ф-я возвращает Ст, то её можно перекрыть, чтобы она возвращала Пт.
  • если запись з1 отличается от записи з2 только тем, что поле з1.П1 - типа Пт, а з2.П1 - типа Ст, то з1 - подтип з2.

Т.е., получается, что отношение между типами зависит не только от самих типов или от их родственности (Конт<Т> могут быть друг другу не родственны или родственны странным образом через Object), но и от контекста применения

Инвариантность - это просто отсутствие ко- или контра-вариантности, т.е. отсутствие предмета обсуждения как такового.

**********************

Прошу проверить правильность моего определения и сказать, все ли случаи применения вариантности в реальных ЯП я перечислил. Про Хаскель пока не спрашиваю, т.к. до функторов ещё не дочитал :) Но можете и про него написать :)

А вот предыдущая тема про это: Ковариантность и динамическая типизация

★★★★★

Последнее исправление: den73 (всего исправлений: 10)

Ответ на: комментарий от ritsufag

Ладно, переделал на csharp. csharp при том, что в нём ковариантность реализована лучше, чем в java, т.е. более продвинутый язык в каких-то аспектах.

den73 ★★★★★
() автор топика

Вместо mono надо было бы поставить тег scala. Там эти понятия получили наибольшее развитие, ибо где еще найти такую сборную солянку ООП + ФП.

Только я пас. У меня от этих вариантностей пропадает всякое желание включать компьютер :)

dave ★★★★★
()
Ответ на: комментарий от den73

Но именно в scala ты смог бы найти ответы на свои вопросы. Например, в книге Одерского.

Только, честно говоря, я редко видел, чтобы вариантность особо применялась на практике. Конечно, мой опыт нерепрезентативен

dave ★★★★★
()
Ответ на: комментарий от dave

Забавно, но если я вменяем, то в SBCL неправильно реализована вариантность для функциональных типов:

(subtypep '(function (integer) t) '(function (t) t) )
T
T
Т.е., по их мнению, «любая функция, отображающая целое на объект, является также функцией, отображающей объект на объект», , хотя в действительности «любая функция, отображающая объект на объект также является функцией, отображающей целое на объект».

Объект aka тип t в лиспе - это любой объект, в т.ч. и целое является подтипом t.

Написал в sbcl-devel, но похоже, что я и их уже достал, и они меня игнорируют :)

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

Ха-ха. А вот LispWorks их не соотносит:

CL-USER 1 > (subtypep '(function (integer) t) '(function (t) t) )
NIL
NIL

CL-USER 2 > (subtypep '(function (t) t) '(function (integer) t) )
NIL
NIL
dave ★★★★★
()
Ответ на: комментарий от dave

Только, честно говоря, я редко видел, чтобы вариантность особо применялась на практике. Конечно, мой опыт нерепрезентативен

Та ладно, всё время и на каждом шагу: типы в списках должны быть ковариативными, возвращаемый тип из функции должен быть контрвариативным. Просто на всяких питонах, жабах и прочем, люди часто внимание не обращают, но если это не соблюдать, оно ж потом не работает. Скала обеспечивает поддержку этого на уровне типов, только и всего.

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от dave

Ха-ха. А вот LispWorks их не соотносит:

Похоже, у Лиспа перспектив мало :-) Тут плакать надо, а не смеяться :-) Никто не собирается объединять усилия, чтобы работать над единой реализацией Лиспа, отсюда такие вот результаты :-) Ну и какой смысл было создавать стандарт, если две реализации реализуют его по-разному и с разными ошибками? :-) Лол :-)

anonymous
()
Ответ на: комментарий от den73

(subtypep '(function (integer) t) '(function (t) t) )

Функция, отображающая целое на объект является частным случаем функции, отображающей объект на объект :-) Потому что integer является подтипом t :-) Так что всё правильно :-)

anonymous
()
Ответ на: комментарий от anonymous

Специально ради тебя включил игнорируемые :-) prin1-to-string отражает объект на объект :-? Да :-) print1-to-string отражает integer на t :-? Да :-) Лол :-) 1+ отражает integer на t :-? да :-) 1+ отражает t на t :-? НЕТ: (1+ «уюшки») ==> error Лол :-)

Итак, существует функция, к-рая отражает integer на t, но которая не отражает t на t Лол

Ты близок к познанию контравариантности :-) Лол

den73 ★★★★★
() автор топика

Постараюсь ответить в меру своего понимания.

Если мы просто передаём параметр, List<Cat> там, где от нас ждут List<T extends Animal>, то мы можем подставить List<Cat> «вместо» List<Animal>, но при этом List<Cat> не становится потомком List<Animal>. Т.е., иерархии никакой нет, а есть заменимость типов в конкретном контексте.

Это же java? Тогда конструктор типа List игнорирует отношение наследования Cat <: Animal, то есть отношения List<Cat> <: List<Animal> нет. Поэтому передать List<Cat> туда, где ожидается List<Animal> нельзя. В случае же, когда мы передаём List<Cat> туда, где ждут List<T extends Animal>, всё норм, так как конкретный тип определяет вызывающая сторона, а принимающая сторона ничего не знает про T и не может поломать список.

Далее, если мы просто пишем Animal *А = new Cat(), то я бы это тоже рассмотрел как ковариантность, хотя здесь нет никаких производных иерархий.

Вариантность - свойство конструкторов типов. Здесь их нет, поэтому и рассматривать нечего.

Вопрос: где же найти правильную статью про ковариантность

Принцип подстановки Барбары Лисков, в общем-то, как раз об этом - нельзя усиливать предусловия и ослаблять постусловия, - так что статьи о нём так или иначе затрагивают сабж, разница в терминологии.

**********************

Моё определение с соответствующими твоим примерами.

Вариантность - свойство конструктора типов, определяющее, каким образом отношение наследования между типами отображается в отношение наследования между результатами применения этого конструктора к этим типам. Например:


  • если S <: T, то S можно использовать в любом месте, где ожидается T (вообще говоря, это определение подтипа);

  • если S <: T и W <: V, то W f(T) <: V f(S), где A f(X) - функция, принимающая аргумент типа X и возвращающая аргумент типа A, т.е. функция ковариантна по типу возвращаемого значения и контравариантна по типу аргумента;

  • если S <: T, то List<S> <: List<T> при отсутствии мутабельности, иначе между ними никакого отношения нет, так называемая подтипизация в глубину;

  • если S <: T, P - объект с полем f типа T, а Q - объект с полем f типа S, то Q <: P, так называемая подтипизация в ширину.



Про Хаскель пока не спрашиваю, т.к. до функторов ещё не дочитал :) Но можете и про него написать :)

А тэг бы поставил, глядишь, набежали бы хаскеллисты, от них в таких темах толку всяко больше, чем от сисярперов.

Laz ★★★★★
()
Ответ на: комментарий от den73

prin1-to-string отражает объект на объект :-? Да :-)

Нет, на string :-)

1+ отражает integer на t :-? да :-)

Нет, на number :-)

1+ отражает t на t :-? НЕТ:

Нет :-) Потому что t - это не integer :-)

Итак, существует функция, к-рая отражает integer на t, но которая не отражает t на t

Нет такой функции :-) Лол :-)

Ты близок к познанию контравариантности :-)

Лол :-)

anonymous
()

Напоминает треды анонiмуса.

anonymous
()
Ответ на: комментарий от Laz

если S <: T, то List<S> <: List<T> при отсутствии мутабельности, иначе между ними никакого отношения нет, так называемая подтипизация в глубину;

Здесь ты упустил случай, когда контейнер только читается. Т.е. он мутабельный, но мы в него не пишем. В грешном мире ещё пока не все контейнеры могут быть иммутабельными. И я думаю, упустил по тому, что сузил понимание вариантности до конструкторов типов. А на самом-то деле оно не обязано быть столь узким.

если S <: T, P - объект с полем f типа T, а Q - объект с полем f типа S, то Q <: P, так называемая подтипизация в ширину.

А вот это я не совсем понял, типы Т и S относятся к полю f или к самим объектами Q и P? Видимо, к f. А каковы тогда типы Q и P? Или ты имел в виду, что Q и P - это типы ,которые отличаются только типом поля f? Если последнее, то такого случая у меня не было. Откуда это, из какого языка?

Хаскелистов потом можно будет позвать. Надо сначала понять, а уж испортить понимание теоркатом никогда не поздно :)

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

И я думаю, упустил по тому, что сузил понимание вариантности до конструкторов типов. А на самом-то деле оно не обязано быть столь узким.

Обязано, потому что у этого термина есть вполне однозначное определение.

Если последнее, то такого случая у меня не было. Откуда это, из какого языка?

typescript, например

let y: number = 5;
let x: { f: string | number } = { f: y };


number < (string | number), по-этому { f: string | number } < { f: number }
без ковариантности вторая строчка бы не сомпилировалась
anonymous
()
Ответ на: комментарий от anonymous

{ f: string | number } < { f: number }

наоборот, конечно

anonymous
()
Ответ на: комментарий от AndreyKl

Наверное, я не так объяснил. Речь не про стандартную библиотеку, а про новый код в проектах

dave ★★★★★
()
Ответ на: комментарий от den73

Хаскелистов потом можно будет позвать. Надо сначала понять, а уж испортить понимание теоркатом никогда не поздно :)

Зачем? Они скажут, что ООП им нафиг не уперлось, и будут правы

dave ★★★★★
()
Ответ на: комментарий от Laz

Ну я понял, наверное, почему ты про конструкторы типов. Это про иммутабельность наверное, т.к. реальная сигнатура функции с побочными эффектами должна включать как-то описание этих побочных эффектов, иначе Лискову не ублажить. Соответственно, «конструкторы типов» хороши тем, что они чисты.

Но в реальном C# есть in и out, которые обрабатывают мутабельность. Так что, как бы это не было изначально, но понятие вариантности в практике программирования шире, чем для конструкторов типов. А меня интересует именно практика.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

про ковариантность

хорошо написано в книгах Бертрана Мейера, например первой или последней, про конструирование.

ЕМНИП, он это понятие и изобрёл

и про реализацию в Eiffel. например, в разрезе проблемы CATCALL вызовов.

правило повторного объявления типов: при повторном переобъявлении типа компонента можно заменить тип компонента или тип формального параметра любым совместимым типом.

.. политика редекларации типов: коваринатная типизация, где «ко» указывает на параллельное изменение типов при спуске по диаграмме наследования.

... понятие опорного элемента

.. необходимо создать механизм не абсолютного, а относительного объявления типа сущности.

проблема: свзазанный список, метод put_right добавляет в хвост. шаблонный LINKABLE_LIST[G], сигнатура метода put_right(v:G). у потомков метод работать не будет, ибо new должен иметь другой тип. поэтому в каждом потомке нужно переопределять весь метод аналогично, только new будет создавать объект другого типа.

...понятие опорного элемента:

first_element: LINKABLE[G] previous, active, next: like first_element

локальная сущность new метода put_right класса LINKED_LIST[G] тоже должна иметь тип like first_element, и это — единственное изменение в процедуре. Теперь достаточно переопределить first_element как BI_LINKABLE в классе TWO_WAY_LIST, как LINKED_TREE в LINKED_TREE, итп. Сущности, описанные как like не нужно указывать в предложении redefine. Не требуется и повторное определение put_right.

.. Опорный элемент Current (like Current = тип self = тип *this)

... правила о закреплённых типах

запрещает циклы в декларативных цепочках. Пусть T — тип anchor (или текущий класс если anchor=Current). Тогда тип like anchor совместим как с самим собой, так и с T.

... тип x опорно-эквивалентен y, если x есть y или имеет тип like z, где z по рекурсии опорно эквивалентен y.

... Правила типизации. Реализм.

ковариантность имеет отношение к статической корректности, и практичности. предлагается реалистичный компромисс, с опорными элементами like anchor.

... Ковариантность и скрытие потомком.

ковариантность — смена типов параметров при переопределении, скрытие потомком — способность класса потомка ограничивать статус экспорта наследуемых.

далее пример про систему учёта в отеле лыжников (и лыжниц). причём нельзя селить вместе лыжницу и лыжника, ибо.

иерархия классов: SKIER, потомки GIRL, BOY, потомки RANKED_GIRL у GIRL, RANKED_BOY у BOY.

определён в предке roommate:SKIER, share(other:SKIER)

переопределяем ковариантно share(other:like roommate), в итоге в потомках переопределяется автоматически, совместимым образом.

Рис. 17.5. Иерархия участников и повторные определения.

Так как наследование является специализацией, то правила типов требуют, чтобы новый тип был потомком исходного. Эта стратегия именуется ковариантностью, где «ко» означает совместное изменение типов параметра и результата. Противоположная стратегия называется контравариантностью.

... Параллельные иерархии.

здесь также нужна ковариантность.

... Корректность систем и классов

Классово-корректна система, удовл. правилам: 1) каждая сущность имеет свой тип 2) тип факт параметра совместим с типом формального 3) вызываемый компонент(метод, свойство) должен быть определён в своём классе и экспортирован классу, содержащему вызов.

системно-корректна система, если при её выполнении не происходит нарушения типов. Ошибка «нарушение системной корректности» = когда классово-корректная система в условиях наследования, ковариантности и скрытия потомком может не быть системно-корректной.

... Контравариантность и безвариантность

... С++ безвариантен (novariance): не позволяет менять тип аргументов в переопределяемых подпрограммах.

... Другое решение: типовые переменные (type variables)

читай Cardelli, Kim Bruce, David Shang, Tony Simons, Castagna, Weber, etc. Приведён список литературы.

... строгое разделение ковариантных и потенциально полиморфных элементов: archor или like anchor ковариантны, остальные полиморфны.

anonymous
()
Ответ на: про ковариантность от anonymous

... Глава Глобальный анализ

Правило системной корректности: x.f(arg) системно-корректен если и только если он классово-корректен для x, arg имеющих любые типы из своих соотв. наборов типов

вызов классово-корректен, если не нарушает правила Вызова Компонентов: если C базовый класс типа x, компонент f должен экспортироваться C, а тип arg должен быть совместимым с типом формального параметра arg.

Системная корректность вызова сводится к классовой корректности за тем искд.чением, что она проверяется не для отдельных компонентов, а для любых пар из наборов множеств.

... остерегайтесь полиморфных кэтколлов!!!11119999

полиморфные кэтколлы некорректны (ибо нельзя)

вызов полиморфен, если его цель полиморфна

сущность х полиморфна, если:

1. x:=y, у по рекурсии полиморфна

2. create OTHER_TYPE x, где OTHER_TYPE не является типом, указанным в объявлении х

3. является формальным аргументом подпрограммы (!!!)

4. является внешней функцией

цель определения - «потенциально полиморфна» любая сущность, присоединяемая к объектам разных типов (ссылочные, кроме inline объектов).

кэтколл := вызов CAT-call (Changing Availability or Type) если некое переопределение подпрограммы сделало бы его ошибочным из-за изменения статуса экспорта или типа аргумента.

... примеры cat-call, примеры полиморфных кэтколлов, правило: полиморфные cat-call-ы ошибочны.

Ковариантность, также как и возможность скрытия потомком компонента в сочетании с полиморфизмом порождает редко встречающуяся, но весьма серьёзную проблему нарушения типов.

Эту проблему можно избежать либо используя глобальный анализ (непрактично), либо ограничивая ковариантность закреплёнными типами (что противоречит принципу «Открыт-Закрыт»), решение Кэтколл, препятствующее вызову полиморфной целью подпрограммы с ковариантностью или скрытием потомком.

... Библиография.

... Руководство по ISE включает введение в проблемы совместного применения полиморфизма, ковариантности и скрытия потомком [M 1988a] также см. [Cook 1989] , [America 1989a], [Weber 1992] [M 1992], [M 1996a], [M-Web]

Обзор ковариантности в [Castagna 1995] [Castagna 1996]

Приёмы на основе типовых переменных [Simons 1995] [Shang 1996] [Bruce 1997]

Контравариантность была реализована в Sather. Пояснения в [Szypersky 1993]

anonymous
()
Ответ на: комментарий от anonymous

из официального сайта ISE Eiffel:

Type safe Eiffel (3, chapter «Covariance» included)

по тегу «catcall»

Can you explain again the difference between conformance and covariance?

What is a CATCALL?

Liberty Eiffel FAQ — бывший SmallEiffel на базе lcc компилятора и прочих; сейчас основано на llvm (ЕМНИП; когда-то была зависимость от GCC-XML)

Кстати, можно потыкать Эйфель. Либо его, Liberty Eiffel,

либо скачать/скачать и собрать дабы потыкать официальный Eiffel Studio, от производителя и фирмы Бертрана Мейера, САМОГО :-)

скачать, релизы, репозитории

очень прикольные презентации, FAQ, документация, обучающее видео

все эйфели умеют транслироваться в си через кодогенерацию.

любопытной уникальной фичей Eiffel Studio являтся AutoTest, см. также тут, поподробнее, туториал, картинкаме

уникальной фичей, в свою очередь, AutoTest является то, что он генерирутся (extract tests) полуавтоматически на основе предусловий, постусловий и инвариантов. То есть, для достаточно откомментированной пред-,пост- условиями и инвариантами стандартной библиотеки или своего кода, студия сама определяет затронутые места и генерирует макеты тестов, которые можно доработать. всё это с удобной GUI-запускалкой тестов, картинкаме.

второй уникальной фичей Eiffel Studio от отца-основателя Бертрана Мейера является поддержка метода BON

если коротко, то UML не обладает reversability: OOA&OOD хорошо работают только в одну сторону, да и тут есть неоднозначности. в обратную с реверсингом всё плохо.

BON, как нотация и метод решает те же задачи, что и UML, но при этом обладает reversability. поскольку есть только 2 типа стрелок (в отличие от диаграммы классов UML): «является клиентом» и «является потомком». поэтому обратимость работает в обе стороны.

подробности — в papers с сайта про метод BON.

в студии эти диаграммы генерируются автоматически, и документация с сайтом проекта — полуавтоматически.

в общем, советую если найдётся время — скачать и потыкать Eiffel (студию, или Libre) самостоятельно. очень интересные ощущения.

всё это совершенно прозрачно интегрируется с кодогенерацией через Си, FFI, .NET/JVM/COM/etc.

компиляторы Eiffel существуют под 10500 OS.

воистину «пиши один раз — скомпилируй подо все платформы, скопом».

anonymous
()
Ответ на: комментарий от den73

Бертран Мейер в Eiffel действительно хорошо понимает ковариантность

anonymous
()
Ответ на: комментарий от Laz

Вопрос: где же найти правильную статью про ковариантность

в книгах Бертрана Мейера про язык Eiffel и кэтколлы catcalls

Принцип подстановки Барбары Лисков, в общем-то, как раз об этом - нельзя усиливать предусловия и ослаблять постусловия, - так что статьи о нём так или иначе затрагивают сабж, разница в терминологии.

там же усиленный объектно-ориентированный принцип Лисков — предусловия и постусловия методов. и композиция, и композабельность (composability) таких вот методов, классов и объектов, предков и потомков. чему пример — AutoTest

anonymous
()
Ответ на: комментарий от den73

иначе Лискову не ублажить.

не ублажить иначе и принципы «Открытости-Закрытости» (см. выше процитированное из книжки).

у Мейера смысл: предок (сервер объекта) содержит наиболее общую спецификацию, сигнатуру, обобщённые определения. потомок (клиент объекта) его специализирует, уточняет.

соответственно, как в обобщённых функциях в CLOS: не должна меняться библиотека с хрупкими базовыми классами предков. вместо этого клиент, потомок при переопределении переопределяет максимально гибко.

например: метод в предке может стать свойством в потомке, и наоборот. может измениться сигнатура, по параллельным иерархиям классов. но изменяться должна осторожно, согласованно : like Current или like that_Objects_type, по всей иерархии.

тогда в клиентах, в потомках тоже ничего менять не придётся.

отсюда — ковариантность.

потом вылазит проблема с полиморфными кэтколлами. если их запретить, то всё ОК.

отсюда — кэтколлы.

отсюда — правила классовой и системной корректности.

отсюда — правила корректности объектной системы типов.

anonymous
()
Ответ на: комментарий от anonymous

или даже наоборот: из идеи создать абсолютно корректно статически «исчисление объектов», а стало быть — объектную систему типов Бертран Мейер в своих книгах начинает с наиболее общей идеи reusability.

затем он расписывает объектно-ориентированный псевдокод, рассуждая о свойствах и правилах такого исчисления объектов. вводит ряд правил, принципов, принципов проектирования и корректности. рассматривает на практичных примерах и иерархиях классов.

и тут как-то получается, что нужна ковариантность, предусловия, контракты, агенты и SCOOP.

и побочный бонус: псевдокод конкретизируется в язык Eiffel, выведенный из свойств «объектно-ориентированного исчисления», из соображений корректной и практичной системы типов (объектных).

а компилятор и язык — получается сам собой, из этих общих принципов.

anonymous
()
Ответ на: комментарий от AndreyKl

тензоръ метапарадигмъ

Только, честно говоря, я редко видел, чтобы вариантность особо применялась на практике. Конечно, мой опыт нерепрезентативен

Та ладно, всё время и на каждом шагу: типы в списках должны быть ковариативными, возвращаемый тип из функции должен быть контрвариативным.

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

интерпретатор суть eval есть отображение (векторного, или пуще того: тензорного поля. сиречь инвариант або свёртка наподобие скалярного произведения) значений на типы.

нехай значения суть ковариантный вектор, а типы — контравариантый. тогда произведение ковариантного тензора на контравариантный суть свёртка, или основная операция вычисляющего интерпретатора. эта парадигма, або модель #1 — интерпретатор.

реализация через Eval Apply это произведение тензоров, ковариантного на контравариантный. то есть, свёртка.

Apply работает с типами, и типы не суть просты, оне — типы высшего порядка. исчислением калькулюса горне-типного исчисляющиеся в простыя типы атомов.

то есть, и исчисление метатипов в тип — тоже суть свёртка.

это модель #2, исчисление типов.

модель #3, або парадигма: компилятор. коий работает с корректными статическими типами.

сиречь метапарадигма.

тут и ковариантность вдругорядь совместно по иерархии, и пред/пост/условия, и композабельность обобщённых функций рода великого и абстрактных базовых пращуров, предками завещаных.

сё есть суть исчисление метапарадигм, ибо метапарадигмы суть поле тензорное, в ходе умножения тензоров сворачивающееся инвариантами в парадигмы конкретныя.

покамест вдосталь аль-кааба сия и ея первоклассныя объекты исчисления сего меркабы лямбда-кубовой не исчислятся наконецъ в модель #1, вычисляющаяся в значения.

невозбранно достигнув желаемого.

anonymous
()
Ответ на: комментарий от den73

А вот это я не совсем понял,

он строит объектное замыкание.

anonymous
()
Ответ на: комментарий от dave

Она применяется вполне себе на практике чуть было не каждый день. Очень часто в этом вопросе можно положиться на компилятор, который тебе всегда подскажет, что вот тут нужно поставить такую вариантность и тогда все будет вообще чики-пики

grouzen ★★
()
Ответ на: комментарий от grouzen

Спасибо за подтверждение, я тоже так думал.

den73 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.