Re[27]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 11:18
Оценка: 1 (1)
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


V>Если речь о пользователях языка, а не о разработчиках компилятора с этого языка, то всем им (нам) должно быть одинаково. ))

Ох, всех подписал, и кому чего должно!

S>>верно. Но цитата из Пирса однозначно отсылает к механике выполнения в рантайме.


V>Не ведись на это. ))

V>Хороший теоретик не обязан быть хорошим инженером, и обратное тоже верно.
Т.е у хороших инженеров свой полиморфизм и определения?

V>Не имеет никакой разницы, как в конечном итоге реализован полиморфизм в конечном бинарном образе.

V>Вернее, это имеет значение, только когда такой полиморфизм реализован ПЛОХО, тогда волей-неволей приходится держать в голове некоторую ЦЕНУ этого полиморфизма. Если же цена реализации близка к 0-лю (в случае С++ или value-type параметров генериков дотнета), то "оно" сразу становится не принципиальным. Ну, т.е. никаких квантов внимания разработчика не потребляет.
Да не нужны там кванты внимания для этого понимания.

S>>И если интерпретатор, рантайм, или еще кто выполняет разные версии кода для разных типов, то это ad hoc.


V>Хороший оптимизатор в итоге и должен сводить подавляющее большинство сценариев к ad hoc.

V>Но это, повторюсь, лишь подробности реализации компилятора, которые могут быть несколько ортогональны "внешним" возможностям ЯП.
Зачем сводить к ad hoc то, что не ad hoc?

V>>>По-сути мы зацепились вокруг того, что хотя компилятор C# в 99% случаев был бы способен разресолвить параметрический полиморфизм на этапе компиляции (т.е. приведя его к ad hoc через вывод монотипов, прямо как на шаблонах С++), однако же, ради "экономии" размера бинарника всё будет сведено к динамическому ad hoc-полиморфизму на основе виртуальных вызовов типов-ограничений (интерфейсов или абстрактных/виртуальных баз).

S>>не вполне распарсил выделенное

V>Монотип — это конкретный тип.


  упс
V>В общем, ясно. ))
V>Попробую разобрать всё это нагромождение "городских легенд" вокруг полиморфизма:

V>Изначально под "типизированностью" понималось оперирование в неких "окончательно определённых типах" в исходнике. Их в Системе F (которую рекламирует Пирс в своей работе "Типы данных") называют "монотипами". Просто термин такой.


V>А теперь смотри на трансформацию понятия "типизированности". Когда речь о монотипах, то тип по классике — это лишь некое множество (допустимых) значений. Когда же идёт речь о полиморфизме, т.е. об АБСТРАГИРОВАНИИ от конкретных типов, то под "типизированностью" в полиморфизме понимают сочетание некоего "черного ящика" (абстрактного типа, чьё множество значений нам НЕИЗВЕСТНО, мы же именно от этого и абстрагируемся) и допустимых операций над ним. Итого, под "типизированностью" в абстрактном программировании понимают набор операций над чёрным ящиком, этому набору дано название "концепт". В Системе F (в Хаскеле/ML), дополнительно к списку операций над абстрактным типом есть еще его "открытая" структура (алг.тип, списки и туплы), в свою очередь состоящая из одного или более "концепта".


V>Итого. Берем обычный ООП-полиморфизм:

V>
V>foreach(Widget w in widgets)
V>  w.Draw(context);
V>

V>Список операций над типом задан нам одним интерфейсом абстрактного класса Widget.

V>А что делать, если мы хотим задать более одного списка операций над "черным ящиком"? Вот только в этом месте возникает параметрический полиморфизм в ООП. В генериках дотнета надо будет задать более одного "ограничения".


V>Ты уже увидел тот прикол, что в случае единственного "ограничения" для генериков дотнета смысла в генериках получается немного? ))

V>У нас там остаётся всего одна "параметрически полиморфная" операция, помимо заданных в списке операций указанного "ограничения" — это копирование "типизированной" ссылки на объект (т.е. экономия на "обслуживании" приведений типов в аргументах и возвращаемых результатах публичных методов, т.е. на генерации бинарного кода выброса исключения в случае неудачного такого приведения). Остальное не сильно отличается от приведённого примера "обычного ООП-полимофизма".

V>А увидел ли еще тот прикол, что в случае Системы F для аналогичного приведённому сниппету уже требуется механизм параметрического полиморфизма + единственное ограничение — Wiget? ))


V>Т.е., прикол в том, что в ООП такой сценарий всё еще НЕ считается параметрическим полиморфизмом, хотя его бинарная механика идентична происходящему в Хаскель в этом же сценарии — в обоих случаях идёт рантайм-матчинг конкретного типа и соответствующей ф-ии Draw по сгенерённой компилятором таблице ф-ий.


V>Далее. Параметрический полиморфизм в ограничениях называют "типизированным параметрическим полиморфизмом". В этом смысле шаблоны С++ дают технику "нетипизированного параметрического полиморфизма". Однако, перегрузка имен ф-ий в области видимости шаблонного кода (и/или перегрузка операторов) таки дают своего рода "ограничения" в том смысле, что если операции из используемых в теле шаблона найти не удалось, то компиляция будет не успешной. Но "открытость" области видимости представляет из себя некоторую опасность, угу. Держим этот момент в уме.


V>Дополнительно в шаблонах С++ доступны типы, определённые внутри других типов (непосредственным образом или через typedef), что дополнительно позволяет определять и использовать отношения м/у типами, где этот механизм с определённой натяжкой можно приравнять к трюку с "открытой структурой" типов в Хаскеле/ML/Системе F. "С натяжкой" — потому что любой матчинг типов должен быть произведён в compile-time. Аналогично с доступом к открытым полям структур (в т.ч. классов и объединений).


V>Я думаю, всего сказанного должно быть достаточно, чтобы понять, как даже на С++ сделать тот самый "типизированный параметрический полиморфизм". Можно использовать операции с явным указанием области видимости — из специального нейспейса или некоего типа — "словаря операций". Т.е., достаточно лишь "закрыть" область поиска перегруженных ф-ий. Список операций над типом из указанной области видимости и будет обеспечивать ту самую "типизированность" в обобщённом программировании, т.е. задавать однозначность ресолвинга нужной ф-ии. И такая техника тоже используется — например, в контейнеры подаётся специальный "словарь" — allocator<T>, где операции над типизированным выделением/освобождением памяти производятся через такой "словарь". Причём, "словарь" может реализовать как статические методы, так и методы экземпляра. Тут в С++ сильно помогает то, что через имя переменной и точку ( al.alloc() ) можно вызывать не только методы экземпляра, но и статические. Т.е., на самом деле всё вместе получается не так уж и грустно, а местами очень даже удобно.

Ты, конечно, извини. Я дважды честно прочитал, но комментировать это все не буду. Местами я согласен, но в остальном — не хочу еще больше флейма, чем мы имеем с таким простым вопросом, как equal_to.

V>Ну вот я тебе дал сниппет ООП-кода. Это тот самый частный случай параметрического полиморфизма, реализованный через динамический ad hoc.


V>А разве принято, скажем, считать, что в Объектном Паскале присутствует параметрический полиморфизм? )) Вот. Поэтому я лишь скромно советую не забивать себе голову попытками тщательного отделения одной разновидности полиморфизма от другой. Тем более, что хороший оптимизатор запросто умеет сводить одно к другому "унутре" (я тут рядом жаловался на то, что компилятор С++ слишкком часто генерит прямые вызовы вместо виртуальных, распространяя своё "зрение" транзитивно, т.е. и в вызываемом коде опять имеет возможность повторить такой же трюк, коль ранее свёл абстрактный тип к монотипу).

Ничего я не забиваю. У меня все стройно, а у тебя какая-то каша, забивающая голову.

V>>>Например, в Хаскеле предопределены некоторые базовые классы типов, необходимые для использования операторов языка: Eq, Ord, Num, Real, Integral, Monad или для базовых операций преобразования в строку — Show. Т.е., совсем "из ничего" не получится.

S>>Вот все что я выделил — это https://wiki.haskell.org/Polymorphism#Ad-hoc_polymorphism
S>>С этим есть разногласия? А я говорил о параметрическом.

V>Это всё параметрический полимофизм тоже. ))

Ты не читал и не согласен, или читал но не согласен, т.к. вики хаскеля писали сантехники для домработниц, а не инженеры?

V>Ты прямо "с самого низа" сразу можешь описывать параметрически полиморфные ф-ии, используя уже предопределённые в рамках стандарта языка "ограничения" — классы Eq, Ord, Num, Show и т.д. Т.е., тебе не всегда нужны свои (пользовательские) классы типов.


Давай я тебе процитирую, что бы ты не пропустил.

You can recognise the presence of ad-hoc polymorphism by looking for constrained type variables: that is, variables that appear to the left of =>, like in elem :: (Eq a) => a -> [a] -> Bool. Note that lookup :: (Eq a) => a -> [(a,b)] -> Maybe b exhibits both parametric (in b) and ad-hoc (in a) polymorphism.

Это по ссылке выше, если что.
То есть, в моем понимании, если ты делаешь в интерпретаторе :t foo и тебе пишут (Eq a) =>, то foo ad hoc полиморфна по типу a.
Просто, не правда ли?


V>>>А вот не надо пытаться тщательно отделять мух от котлет, когда речь о полиморфизме. ))

V>>>Потому что это зачастую банально невозможно.
S>>Что тут сложного? equal_to — ad hoc, Eq a — ad hoc.

V>А тут:

V>
V>equal_to :: (Eq a) => a -> a -> Bool
V>equal_to a b = (a == b)
V>

V>?
см выше. Ad hoc.

S>>Но если внезапно из рассмотрения выкинуть все типы, кроме тех, у которых определен оператор == или инстанс Eq, то тогда они выглядят как параметрические.


V>Ну вот я против таких заморачиваний и выступал в прошлом сообщении, что это всё условности. Ты можешь считать так, что моё определение equal_to для Хаскеля — это всегда параметрический полиморфизм. Такой подход можно назвать "строгим", теоретикам навроде Пирса нравится. А тот факт, что Хаскель способен в 99% случаев привести его к ad hoс через оптимизацию и/или вывод типов в конкретном контексте — лишь приятный бонус, эдакий побочный эффект. ))

да не, я как раз считаю что твое определение equal_to для Хаскеля — это ad hoc. И этого не спрятать 10ю обертками equal_to_10 над equal_to_N. Можно попытаться сотней, но я не уверен что получится.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.