Форум
Компьютерные священные войны
Тема
Как правильно задавать вопросы
B
I
abc
U
X
3
X
3
H1
H2
H3
H4
H5
H6
Asm
C/C++
C#
Erlang
Haskell
IDL
Java
Lisp
MSIL
Nemerle
ObjC
OCaml
Pascal
Perl
PHP
Prolog
Python
Ruby
Rust
SQL
VB
Здравствуйте, vdimas, Вы писали: V>Здравствуйте, samius, Вы писали: V>>>А только это и важно. :xz: S>>Кому как V>Если речь о пользователях языка, а не о разработчиках компилятора с этого языка, то всем им (нам) должно быть одинаково. )) V>>>С другой стороны есть механики его обеспечения компилятором - матчинг типа и соответствующей ему ф-ии/метода на этапе компиляции/оптимизации или на этапе исполнения через таблицу ф-ий, как для случая виртуальных ф-ий в ООП или в некоторых сценариях с использованием классов типов в том же Хаскеле. S>>верно. Но цитата из Пирса однозначно отсылает к механике выполнения в рантайме. V>Не ведись на это. )) V>Хороший теоретик не обязан быть хорошим инженером, и обратное тоже верно. V>Не имеет никакой разницы, как в конечном итоге реализован полиморфизм в конечном бинарном образе. V>Вернее, это имеет значение, только когда такой полиморфизм реализован ПЛОХО, тогда волей-неволей приходится держать в голове некоторую ЦЕНУ этого полиморфизма. Если же цена реализации близка к 0-лю (в случае С++ или value-type параметров генериков дотнета), то "оно" сразу становится не принципиальным. Ну, т.е. никаких квантов внимания разработчика не потребляет. S>>И если интерпретатор, рантайм, или еще кто выполняет разные версии кода для разных типов, то это ad hoc. V>Хороший оптимизатор в итоге и должен сводить подавляющее большинство сценариев к ad hoc. :xz: V>Но это, повторюсь, лишь подробности реализации компилятора, которые могут быть несколько ортогональны "внешним" возможностям ЯП. V>>>Неверно. Тут в разные годы пробегали примеры на Хаскель с использованием классов типов, где без динамического матчинга времени исполнения никак - компилятор Хаскель создаёт таблицы ф-ий для их инстансов для конкретных типов. S>>Согасен. Для программиста это выглядит статически, а в рантайме может использоваться динамика для избежания распухания, или по каким-то другим мотивам. Статика или динамика не сказывается на универсальности. V>Вот. V>>>По-сути мы зацепились вокруг того, что хотя компилятор C# в 99% случаев был бы способен [b]разресолвить параметрический полиморфизм на этапе компиляции (т.е. приведя его к ad hoc через вывод монотипов[/b], прямо как на шаблонах С++), однако же, ради "экономии" размера бинарника всё будет сведено к динамическому ad hoc-полиморфизму на основе виртуальных вызовов типов-ограничений (интерфейсов или абстрактных/виртуальных баз). S>>не вполне распарсил выделенное V>Монотип - это конкретный тип. V>В общем, ясно. )) V>Попробую разобрать всё это нагромождение "городских легенд" вокруг полиморфизма: V>Изначально под "типизированностью" понималось оперирование в неких "окончательно определённых типах" в исходнике. Их в Системе F (которую рекламирует Пирс в своей работе "Типы данных") называют "монотипами". Просто термин такой. V>А теперь смотри на трансформацию понятия "типизированности". Когда речь о монотипах, то тип по классике - это лишь некое множество (допустимых) значений. Когда же идёт речь о полиморфизме, т.е. об АБСТРАГИРОВАНИИ от конкретных типов, то под "типизированностью" в полиморфизме понимают сочетание некоего "черного ящика" (абстрактного типа, чьё множество значений нам НЕИЗВЕСТНО, мы же именно от этого и абстрагируемся) и допустимых операций над ним. Итого, [i]под "типизированностью" в абстрактном программировании понимают набор операций над чёрным ящиком[/i], этому набору дано название "концепт". В Системе F (в Хаскеле/ML), дополнительно к списку операций над абстрактным типом есть еще его "открытая" структура (алг.тип, списки и туплы), в свою очередь состоящая из одного или более "концепта". V>Итого. Берем обычный ООП-полиморфизм: V>[cs] V>foreach(Widget w in widgets) V> w.Draw(context); V>[/cs] V>Список операций над типом задан нам [i]одним[/i] интерфейсом абстрактного класса Widget. V>А что делать, если мы хотим задать [i]более одного[/i] списка операций над "черным ящиком"? Вот только в этом месте возникает параметрический полиморфизм в ООП. В генериках дотнета надо будет задать более одного "ограничения". V>Ты уже увидел тот прикол, что в случае единственного "ограничения" для генериков дотнета смысла в генериках получается немного? )) V>У нас там остаётся всего одна "параметрически полиморфная" операция, помимо заданных в списке операций указанного "ограничения" - это копирование "типизированной" ссылки на объект (т.е. экономия на "обслуживании" приведений типов в аргументах и возвращаемых результатах публичных методов, т.е. на генерации бинарного кода выброса исключения в случае неудачного такого приведения). Остальное не сильно отличается от приведённого примера "обычного ООП-полимофизма". V>А увидел ли еще тот прикол, что в случае Системы F для аналогичного приведённому сниппету уже требуется механизм параметрического полиморфизма + единственное ограничение - Wiget? )) V>Т.е., прикол в том, что в ООП такой сценарий всё еще НЕ считается параметрическим полиморфизмом, хотя его бинарная механика идентична происходящему в Хаскель в этом же сценарии - в обоих случаях идёт рантайм-матчинг конкретного типа и соответствующей ф-ии Draw по сгенерённой компилятором таблице ф-ий. V>Далее. Параметрический полиморфизм в ограничениях называют "типизированным параметрическим полиморфизмом". В этом смысле шаблоны С++ дают технику "нетипизированного параметрического полиморфизма". Однако, перегрузка имен ф-ий в области видимости шаблонного кода (и/или перегрузка операторов) таки дают своего рода "ограничения" в том смысле, что если операции из используемых в теле шаблона найти не удалось, то компиляция будет не успешной. Но "открытость" области видимости представляет из себя некоторую опасность, угу. Держим этот момент в уме. ;) V>Дополнительно в шаблонах С++ доступны типы, определённые внутри других типов (непосредственным образом или через typedef), что дополнительно позволяет определять и использовать [i]отношения[/i] м/у типами, где этот механизм с определённой натяжкой можно приравнять к трюку с "открытой структурой" типов в Хаскеле/ML/Системе F. "С натяжкой" - потому что любой матчинг типов должен быть произведён в compile-time. Аналогично с доступом к открытым полям структур (в т.ч. классов и объединений). V>Я думаю, всего сказанного должно быть достаточно, чтобы понять, как даже на С++ сделать тот самый "типизированный параметрический полиморфизм". Можно использовать операции с явным указанием области видимости - из специального нейспейса или некоего типа - "словаря операций". Т.е., достаточно лишь "закрыть" область поиска перегруженных ф-ий. Список операций над типом из указанной области видимости и будет обеспечивать ту самую "типизированность" в обобщённом программировании, т.е. задавать однозначность ресолвинга нужной ф-ии. И такая техника тоже используется - например, в контейнеры подаётся специальный "словарь" - allocator<T>, где операции над типизированным выделением/освобождением памяти производятся через такой "словарь". Причём, "словарь" может реализовать как статические методы, так и методы экземпляра. Тут в С++ сильно помогает то, что через имя переменной и точку ( al.alloc() ) можно вызывать не только методы экземпляра, но и статические. Т.е., на самом деле всё вместе получается не так уж и грустно, а местами очень даже удобно. :xz: V>>>Разные виды полиморфизма ни в коем случае не ортогональны друг другу, а часто друг через друга выражаются или некие случаи представляют из себя одновременно несколько разновидностей полиморфизма. Поэтому, ИМХО, - это рассуждения вникуда, когда пытаются один вид полиморфизма "тщательно отделить" от другого. S>>Не вполне согласен. Есть чистые случаи (пусть они крайности), есть комбинированные. V>Ну вот я тебе дал сниппет ООП-кода. Это тот самый частный случай параметрического полиморфизма, реализованный через динамический ad hoc. V>А разве принято, скажем, считать, что в Объектном Паскале присутствует параметрический полиморфизм? )) Вот. Поэтому я лишь скромно советую не забивать себе голову попытками тщательного отделения одной разновидности полиморфизма от другой. Тем более, что хороший оптимизатор запросто умеет сводить одно к другому "унутре" (я тут рядом жаловался на то, что компилятор С++ слишкком часто генерит прямые вызовы вместо виртуальных, распространяя своё "зрение" транзитивно, т.е. и в вызываемом коде опять имеет возможность повторить такой же трюк, коль ранее свёл абстрактный тип к монотипу). V>>>Например, в Хаскеле предопределены некоторые базовые классы типов, необходимые для использования операторов языка: [b]Eq, Ord, Num, Real, Integral, Monad[/b] или для базовых операций преобразования в строку - [b]Show[/b]. Т.е., совсем "из ничего" не получится. :xz: S>>Вот все что я выделил - это https://wiki.haskell.org/Polymorphism#Ad-hoc_polymorphism S>>С этим есть разногласия? А я говорил о параметрическом. V>Это всё параметрический полимофизм тоже. )) V>Ты прямо "с самого низа" сразу можешь описывать параметрически полиморфные ф-ии, используя уже предопределённые в рамках стандарта языка "ограничения" - классы Eq, Ord, Num, Show и т.д. Т.е., тебе не всегда нужны свои (пользовательские) классы типов. V>>>А вот не надо пытаться тщательно отделять мух от котлет, когда речь о полиморфизме. )) V>>>Потому что это зачастую банально невозможно. S>>Что тут сложного? equal_to - ad hoc, Eq a - ad hoc. V>А тут: V>[haskell] V>equal_to :: (Eq a) => a -> a -> Bool V>equal_to a b = (a == b) V>[/haskell] V>? S>>Но если внезапно из рассмотрения выкинуть все типы, кроме тех, у которых определен оператор == или инстанс Eq, то тогда они выглядят как параметрические. V>Ну вот я против таких заморачиваний и выступал в прошлом сообщении, что это всё условности. Ты можешь считать так, что моё определение equal_to для Хаскеля - это всегда параметрический полиморфизм. Такой подход можно назвать "строгим", теоретикам навроде Пирса нравится. А тот факт, что Хаскель способен в 99% случаев привести его к ad hoс через оптимизацию и/или вывод типов в конкретном контексте - лишь приятный бонус, эдакий побочный эффект. ))
Теги:
Введите теги разделенные пробелами. Обрамляйте в кавычки словосочетания с пробелами внутри, например:
"Visual Studio" .NET
Имя, пароль:
Загрузить
Нравится наш сайт?
Помогите его развитию!
Отключить смайлики
Получать ответы по e-mail
Проверить правописание
Параметры проверки …