Re[54]: «Собаку съел»
От: alex_public  
Дата: 13.02.17 13:39
Оценка: -1 :)
Здравствуйте, samius, Вы писали:

_>>Мне вот интересно, а ты способен вообще начать формулировать свои мысли с помощью технической терминологии, а не бытовой? А то понятие "поведение" же можно интерпретировать как угодно.

S>Мне вот интересно было, перейдешь ли ты на оценку способностей собеседника в явной форме? Благодарю что удовлетворил интерес.

Оценки пока не было, был лишь вопрос. Но судя по всему при подобном продолжение дискуссии уже будет недалеко и до оценки, отрицательной естественно.

_>>Например вот возьму я две одинаковые функции, определённые отдельно (перегрузка) для float и для double и скажу что у них абсолютно одинаковое поведение (скажем "сложение чисел с плавающей точкой"). С твоей позиции это получается параметрический полиморфизм? )))

S>С твоей интерпретацией слова "абсолютно" я уже знаком. Чем больше находится опровержений, тем более "абсолютна" становится твоя мысль. На мой взгляд, то что ты говоришь что поведение сложения чисел с плавающей точкой абсолютно одинаковое — еще не делает его таким для разных представлений чисел. Но говорить ты можешь.

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

_>>Я не ввожу разные полиморфизмы — классическое определение с безликим "код" вполне мне подходит. Я просто применяю его на двух отдельных уровнях размышления.

S>Так, что это тебе дало, кроме путаницы при общении и разногласии с источниками?

Разногласия никакого нет. В источниках указывается безликое "код", без всяких уточнений. А я лишь конкретизирую к чему конкретно я применяю это стандартное определение. А даёт это понимание реальных процессов, а не фантазий программиста.

_>>Потому что нет такого термина как поведение. Сформулируй свою мысль в технических терминах, а не так, чтобы его можно было интерпретировать как угодно, в зависимости от выгоды конкретной ситуации.

S>Ты же интерпретируешь. Я тебе уже писал, что именно подразумевают под поведением люди в научной среде. Но тебе все время хочется съехать то на поведение уровня текста, то на поведение уровня количества вызовов.

О, как интересно... Ещё совсем недавно ты писал, что "поведение" — это обычный бытовой термин. А сейчас уже оказывается, что какой-то вполне себе научный термин. Ну давай тогда, озвучь его чёткое определение. Его же не может не быть, если это реально технический термин, который все понимают однозначно.

_>>Вот любишь ты использовать скользкие понятия. Вот скажи мне, например в случае Хаскеля в его "execution model" входит тот факт, что в языке есть только функции одного аругмента (а запись вроде как функции нескольких просто является упрощённой записью последовательности нескольких вызовов)? Или же там наоборот указано, что данные объявления последовательностей вызовов в реальности превращаются в классические функции многих аргументов? )

S>В стандарте языка указано лишь как записывается function application, и что оно левоассоциативно. Остальное — детали частной реализации, не имеющие значения с точки зрения поведения. Но имеющие с точки зрения оптимизации, если ты хочешь об этом услышать. Впрочем, это не повод тащить эти детали на уровень языка.

Как мило. ))) Интересно, а что тогда по твоему входит в "execution model" скажем языка C++? )))

_>>И? ) Так какой тогда полиморфизм у apply? )

S>параметрический

Т.е. можно быть параметрически полиморфной и при этом иметь в глубинах своего стека вызовов ad hoc код? )

S>>>В то время, как equal_to и my_equal_to просто неотделимы от выполнения специального кода для каждого типа.

_>>Ну вообще то это не так даже для equal_to, т.к. мы можем определить единый для всех типов оператор равенства (понятно что смысла в подобном мало, но сам факт подобной возможности однозначен).
S>Определить — то мы можем, но и поведение изменится.

Конечно. Но при этом сама функция то не изменится. Получается, что при твоём подходе полиморфизм подобной функции определяется не по её личным свойствам, а по параметрам какого-то постороннего кода.

_>>А уж для my_equal_to это на 100% не верно, потому как в ней происходит вполне себе параметрически полиморфный вызов оператора равенства для типа eq и всё — что там происходит внутри этого оператора (разный код для разных типов или нет) my_equal_to не касается.

S>Это твое частное мнение, которое нечем подкрепить. Оно расходится, как минимум (кроме определений), с работами Wadler-а по введению классов типа, расходится с методами классификации, предлагаемыми хаскельвики.

А какое отношение имеют классы типов и хаскельвики к коду на C++? )

_>>Я надеюсь ты сам то понимаешь, что демонстрацией только подобных примеров ты ещё больше подчёркиваешь мою правоту? )

S>Нет, я воспитан в кругах, где для опровержения тезиса достаточно одного контрпримера. Особенно тезиса, сформулированного с помощью сочетания "абсолютно все". Но у тебя — ровно наоборот: каждый контрпример подчеркивает твою правоту.

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

_>>А как там внутри реализован eq — это уже его дело, про которое my_equal_to никак не в курсе. Т.е. я могу поменять отдельно реализацию eq как мне угодно и соответственно изменится поведение my_equal_to, даже если она уже собрана в отдельный бинарный модуль. Не видишь ничего общего с apply? )

S>Пока my_equal_to сравнивает значения разных типов специальным образом в соответствии с типом — ничего общего с apply у нее нет. Если my_equal_to начинает сравнивать значения разных типов универсальным образом, то у нее нет ничего общего со сравнением типов через оператор == с соответствующим поведением.

my_equal_to сравнивает значения универсальным образом — через оператор равенства типа eq. ) Похоже именно этот момент ты никак не можешь осознать. Хотя вроде как самая элементарная абстракция...
Re[10]: IEquatable<T>
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.02.17 18:59
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>Ситуация была простая — ты мне дал некую ссылку, я по ней прошел, увидел сниппет кода и сообщил, что вызывается метод базового Object. После этого ты 4 поста тормозишь как стадо Камазов, хотя я тебе уже прямо сообщил, что и как вышло.

S>>Так это все-таки "извини, был неправ, невнимателен, так вышло"?

V>А почему я был не прав? ))

V>Мне кидают ссылку с простынёй кода.
V>Не объясняют даже ЗАЧЕМ.
V>Т.е. в оппонента летит ссылка БЕЗ внятной аргументации.

V>Я не прав был, что не изучил её (простыню) всю? ))

Сам же и ответил. Не поняв, ЗАЧЕМ, изучил всю, вынес вердикт не о том, о чем была дана ссылка и контекст.

V>Вместо такого фокуса коллега мог назвать конкретный метод конкретного типа и никаких ссылок не надо — кому попервой и даже любопытно, пусть смотрит сам. А остальным, кто еще 12-15 лет назад это всё уже прожевал и выкакал, сорри, тому банально не любопытно глазеть на подобный код.

Коллега понадеялся что контекста обсуждения было достаточно. А в отношении любопытства остальных — согласен. Возможность — юслес на 99% (ИМХО).

V>Дотнет на сегодня — это уже довольно древняя технология, об этом надо таки помнить. Оно ведь даже скорее раздражает, когда собеседник пытается спорить и аргументировать вот на таком уровне.

80% технологий еще древнее. Если не больше.

V>В общем, озвуч он членораздельно свой аргумент, и я сходу бы ему и ответил, почему его аргумент кривой, косой и не канает. Потому что, с начала всех начал, его пример НЕ является примером:

V>1. там в любом случае происходит вызов метода интерфейса;
Вероятно, но вызов метода интерфейса не через интерфейс там тоже происходит.
V>2. дефолтный компаратор порождается через рефлексию; особенно весело сие после пространных рассуждений коллеги о "безопасной компиляции";
Как создается дефолтный компарер — не имеет отношения. Тем более, что он кэшируется.
V>3. коллега пытался аргументировать об одинаковой работе для случая value-type и ref-type, но приводит такой пример, где методы типа Т не вызываются вовсе, а вызываются методы исключительно ref-типа IComparer<T> (в теле генерик-метода);
а методы IEquatable<T> каким образом вызываются? О них ведь речь была.

V>И о последнем так же уже было уже сказано ему же рядом более одного раза. И даже было сказано, как это можно было бы исправить (в каких-нить своих коллекциях, например). Однако же, однако же... Это такая разновидность слепоты? Или гипертрофированная инерционность? Что это вообще было? ))


V>Этого коллеге показалось мало и его стало заносить далее: " ты даже на джуниора не потянул бы, ты совершенно не понимаешь происходящего".

V>Мамая мия.
Я полагаю что вы говорили о чем-то разном, подразумевая что об одном и том же.

V>В итоге, коллега заслуженно был подвергнут нещадной обструкции.

V>Причем, весьма мягкой, ИМХО, учитывая происходящее целиком. ))
Мягко, но нещадно. Интересно.

V>============

V>Хотя, если упустить весь рисунок развития ситуации, согласен, моя реакция может показаться странной. Там надо на десяток постов вверх подниматься и смотреть на картинку целиком.
Смотрел вчера, картина не стоит того.

V>=========

V>Ну вот я тебе пишу тут, ОК.
V>Много.
V>По одной простой причине — ты обычно сходу понимаешь, что тебе пишут. ))
Жаль, меня обычно не сходу ))
V>Смотри как мало надо собеседнику для счастья.
После месяца непонимания...
Re[55]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.02.17 19:11
Оценка:
Здравствуйте, alex_public, Вы писали:

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


S>>Мне вот интересно было, перейдешь ли ты на оценку способностей собеседника в явной форме? Благодарю что удовлетворил интерес.


_>Оценки пока не было, был лишь вопрос. Но судя по всему при подобном продолжение дискуссии уже будет недалеко и до оценки, отрицательной естественно.

Вах, баюс

S>>С твоей интерпретацией слова "абсолютно" я уже знаком. Чем больше находится опровержений, тем более "абсолютна" становится твоя мысль. На мой взгляд, то что ты говоришь что поведение сложения чисел с плавающей точкой абсолютно одинаковое — еще не делает его таким для разных представлений чисел. Но говорить ты можешь.


_>Вот в том то и дело что могу. Более того, это будет абсолютно адекватное рассуждение, на которое ни один нормальный программист не возразит. Потому что понятие "поведение" не является каким-то термином и в одном из вариантов его применения к данной ситуации это будет справедливо.

Опять кванторы, смысл которых ты не постиг.

S>>Так, что это тебе дало, кроме путаницы при общении и разногласии с источниками?


_>Разногласия никакого нет. В источниках указывается безликое "код", без всяких уточнений. А я лишь конкретизирую к чему конкретно я применяю это стандартное определение. А даёт это понимание реальных процессов, а не фантазий программиста.

Отсюда можно сделать вывод: твое понимание реальных процессов зависимо от способа трактовки терминологии. Гламурненько.

_>>>Потому что нет такого термина как поведение. Сформулируй свою мысль в технических терминах, а не так, чтобы его можно было интерпретировать как угодно, в зависимости от выгоды конкретной ситуации.

S>>Ты же интерпретируешь. Я тебе уже писал, что именно подразумевают под поведением люди в научной среде. Но тебе все время хочется съехать то на поведение уровня текста, то на поведение уровня количества вызовов.

_>О, как интересно... Ещё совсем недавно ты писал, что "поведение" — это обычный бытовой термин. А сейчас уже оказывается, что какой-то вполне себе научный термин. Ну давай тогда, озвучь его чёткое определение. Его же не может не быть, если это реально технический термин, который все понимают однозначно.

Я не говорил, что это строго научный термин. Я говорил что под ним обычно понимают. И не говорил, что однозначно. Скорее, схожим образом (кроме тебя). Терпение. Чуть ниже.

S>>В стандарте языка указано лишь как записывается function application, и что оно левоассоциативно. Остальное — детали частной реализации, не имеющие значения с точки зрения поведения. Но имеющие с точки зрения оптимизации, если ты хочешь об этом услышать. Впрочем, это не повод тащить эти детали на уровень языка.


_>Как мило. ))) Интересно, а что тогда по твоему входит в "execution model" скажем языка C++? )))

А зачем по-моему, если ты можешь открыть и почитать? Вот открой спецификацию C++, обещаю, много чего найдешь нового. И про "execution model", которая там называется "Program execution", и про абстрактную машину, и даже про поведение кода (там "observable behavior of the program"). Но там не про вообще, а про конкретно C++ модели, машину и поведение. Авторы книг, откуда я цитировал, использовали более обобщенные понятия (более интуитивные).

Так вот, если ты не открывал спецификацию даже С++ (за который ты тут пилишь), или открывал, но она прошелестела мимо, о каком понимании реальных процессов идет речь вообще? Это риторический вопрос. Не трудись отвечать.

_>Т.е. можно быть параметрически полиморфной и при этом иметь в глубинах своего стека вызовов ad hoc код? )

Мы это уже проходили неоднократно. Отмотай назад, мое мнение не изменилось. А желание тебе разжевывать — поубавилось.

S>>>>В то время, как equal_to и my_equal_to просто неотделимы от выполнения специального кода для каждого типа.

_>>>Ну вообще то это не так даже для equal_to, т.к. мы можем определить единый для всех типов оператор равенства (понятно что смысла в подобном мало, но сам факт подобной возможности однозначен).
S>>Определить — то мы можем, но и поведение изменится.

_>Конечно. Но при этом сама функция то не изменится. Получается, что при твоём подходе полиморфизм подобной функции определяется не по её личным свойствам, а по параметрам какого-то постороннего кода.

О, только что у apply переданный параметром код был не посторонний.

S>>Это твое частное мнение, которое нечем подкрепить. Оно расходится, как минимум (кроме определений), с работами Wadler-а по введению классов типа, расходится с методами классификации, предлагаемыми хаскельвики.


_>А какое отношение имеют классы типов и хаскельвики к коду на C++? )

А причем вообще С++? Когда ты вклинился, в контексте темы "инлайна параметрических компареров" никакого C++ не было.

S>>Нет, я воспитан в кругах, где для опровержения тезиса достаточно одного контрпримера. Особенно тезиса, сформулированного с помощью сочетания "абсолютно все". Но у тебя — ровно наоборот: каждый контрпример подчеркивает твою правоту.


_>Мне не интересно играть в подобные игры для детей. Я тебя попросил продемонстрировать хоть одну реальную функцию, удовлетворяющую твоим критериям параметрического полиморфизма. И я думаю ты прекрасно понял о чём речь. Но судя по тому, что я сейчас вижу, ты просто не можешь этого сделать.

Я продемонстрировал вместо "хоть одной" даже две, если не ошибаюсь. Чем должен был поставить тебя в неловкое положение, но ты его сам делаешь еще более неловким, продолжая употреблять кванторы, суть которых пронеслась мимо твоего сознания, как, похоже, и многое другое.

_>>>А как там внутри реализован eq — это уже его дело, про которое my_equal_to никак не в курсе. Т.е. я могу поменять отдельно реализацию eq как мне угодно и соответственно изменится поведение my_equal_to, даже если она уже собрана в отдельный бинарный модуль. Не видишь ничего общего с apply? )

S>>Пока my_equal_to сравнивает значения разных типов специальным образом в соответствии с типом — ничего общего с apply у нее нет. Если my_equal_to начинает сравнивать значения разных типов универсальным образом, то у нее нет ничего общего со сравнением типов через оператор == с соответствующим поведением.

_>my_equal_to сравнивает значения универсальным образом — через оператор равенства типа eq. ) Похоже именно этот момент ты никак не можешь осознать. Хотя вроде как самая элементарная абстракция...

Ну раз так, то перегрузка оператора == тоже сравнивает значения универсальным образом: через оператор ==. (Это называется противоречием. Их вроде бы даже раньше школьная программа включала. Жаль, что оно лишь убедит тебя в собственной правоте)
Re[11]: IEquatable<T>
От: vdimas Россия  
Дата: 14.02.17 03:11
Оценка:
Здравствуйте, samius, Вы писали:

V>>Я не прав был, что не изучил её (простыню) всю? ))

S>Сам же и ответил. Не поняв, ЗАЧЕМ, изучил всю, вынес вердикт не о том, о чем была дана ссылка и контекст.

Потому что это было уныло — расписывать.
Я хорошо понял зачем.
Унылость была в том, что коллега не расписал свой аргумент, т.е. отвечать было не нечего, а не на что. Начался отрезок бессмыслицы в обсуждении.

Я его просто ткнул носом в слабость его аргумента и удивился потом с того, что коллега даже не понял, во что именно я его ткнул. ))
И еще показал, что я подобных флуктуаций его сознания уже ожидал:
http://www.rsdn.org/forum/flame.comp/6662410.1

Там действительно, лишь флуктуация.
Т.е. человек помнит "трюк" насчет ограничений генерик-аргументов, но не помнит, куда и как его можно применять.


V>>Вместо такого фокуса коллега мог назвать конкретный метод конкретного типа и никаких ссылок не надо — кому попервой и даже любопытно, пусть смотрит сам. А остальным, кто еще 12-15 лет назад это всё уже прожевал и выкакал, сорри, тому банально не любопытно глазеть на подобный код.

S>Коллега понадеялся что контекста обсуждения было достаточно. А в отношении любопытства остальных — согласен. Возможность — юслес на 99% (ИМХО).

Коллега не умеет формулировать свои мысли. Если бы он попытался формально расписать свой аргумент, то САМ увидел бы, что его аргумент НЕ канает. Бо в хорошем вопросе содержится половина ответа. И тут как раз тот случай.

Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.
Он ведь правильно пишет (по наитию, скорее):

Как он (comparer) там создаётся вообще пофигу.

"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.

Но оно не пофигу, коль он взялся опровергать вот это:

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

Потому что из-за отсутствия связи на уровне типов в этом месте НЕЛЬЗЯ подать value-type GenericEqualityComparer<T> where T : IEquatable<T>, даже если бы сигнатура метода была примерно такая:
class List<T> {
 public int IndexOf<TComparer>(T value, Comparer comparer) where TComparer : IEqualityComparer<T> {...}
...
}

Т.е. в этом месте можно было бы подать лишь НЕ генерик-реализацию в случае value-type компаратора, т.е. его аргумент аннигилируется без моей помощи. ))

Потому что требуемое ограничение надо было бы распространить выше:
class List<T> where T : IEquatable<T>

что являлось бы суровым ограничением.

Итого, что мы имеем:
* В самом алгоритме целевого метода используется техника, описанная мною тут и тут.

Оттуда:

я и сам смогу тебе привести сходу пример, где такой полиморфизм сможет разресолвится статически в дотнете, я уже озвучивал — это при использовании технологии "объекта-словаря операций" (и в приводимых к этой концепции сценариях), где сам такой объект представлен value-типом. Ну не популярная эта техника нифига в дотнете. Там никто не таскает в логике эти словари рядом с целевыми объектами, везде идёт попытка работать с объектами напрямую. А когда напрямую, то возвращаемся к самому первому моему утверждению:
Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.

Потому что получается так, что лишь теми операциями, которыми обложили базу объекта (интефейс интерфейса или публичный интерфейс базового класса) и можно оперировать. И шаг вправо-влево сделать вааще никак.

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


* Мне приводят пример, где GenericEqualityComparer<T> создаётся через рефлексию, потому что система типов не позволяет указать его явно в исходнике.

* В целевом алгоритме НЕТ никакого трюка по вызову методов целевого типа T.

* Все операции делаются через т.н. "словарь операций", где сам словарь НЕ обязан быть генерик-словарём, там используется обычный ООП-интерфейс.

* вызов методов у целевого T происходит только здесь:
internal class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
{
    public override bool Equals(T x, T y)
    {
        if (x != null)
        {
            if (y != null) return x.Equals(y);
            return false;
        }
        if (y != null) return false;
        return true;
    }
}

Что в случае специализации в рантайме конкретным value-типом, отличным от Nullable<T2>, например, простым int (не суть важно, просто пример конкретного типа) даст вот такой код:
    public override bool Equals(int x, int y)
    {
       return x.Equals(y);
    }


Вот ЭТО и есть пример "алгоритма"?

===================
Я бы мог всё это дать сразу, но тут сработал такой момент, что когда собеседник "претендует" на некий уровень (а сходу взятый надменно-язвительный тон и регулярное переименование заголовков сообщений в некие "намеки" означает именно это, верно?), то сей "уровень" надо ж уметь поддерживать, не? ))

В общем, я не должен был всю эту банальщину тут расписывать. Ведь со стороны дотнета выступал не я. А то получается, что я должен был начать сам с собой спорить, бо оппонент за себя не тянет.


V>>Дотнет на сегодня — это уже довольно древняя технология, об этом надо таки помнить. Оно ведь даже скорее раздражает, когда собеседник пытается спорить и аргументировать вот на таком уровне.

S>80% технологий еще древнее. Если не больше.

Верно. Поэтому совсем уж заходить на банальности, а тем паче начинать плавать по ним — это банально моветон.
Тем более, плавать со "своей стороны баррикад". ))


V>>В общем, озвуч он членораздельно свой аргумент, и я сходу бы ему и ответил, почему его аргумент кривой, косой и не канает. Потому что, с начала всех начал, его пример НЕ является примером:

V>>1. там в любом случае происходит вызов метода интерфейса;
S>Вероятно, но вызов метода интерфейса не через интерфейс там тоже происходит.

И ты, Брут?
Нет, не происходит.

С точки зрения метода IndexOf, мы вызываем методы "черного ящика" — поданного извне словаря операций. Вызовы метода по ограничениям — это уже подробности реализации этого черного ящика и никак не связаны с целевым алгоритмом. Более того, уже показал выше, почему этот "черный ящик" не может иметь генерик-реализацию value-type в системе типов, т.е. у нас тут получаются ДВА независимых разных алгоритма, работающих совместно.

Т.е., мы заведомо имеем дело с "нетипизированным параметрическим полиморфизмом".
Подробно я описывал тут: http://www.rsdn.org/forum/flame.comp/6680620.1

Блин, ну вот целиком пример (заставляете тратить время на запуск Студии, бо я уже и сам начинаю сомневаться, ы-ы-ы):
    struct GenericEqualityComparer<T> : IEqualityComparer<T> where T : IEquatable<T>
    {
        public bool Equals(T x, T y)
        {
            if (x != null)
            {
                if (y != null) return x.Equals(y);
                return false;
            }
            if (y != null) return false;
            return true;
        }

        public int GetHashCode(T obj)
        {
            throw new NotImplementedException();
        }
    }

    class MyList<T>
    {
        public int IndexOf<TComparer>(T value, TComparer comparer) where TComparer : IEqualityComparer<T>
        {
            return 0; // заглушка
        }

        // Не компиллируется! 
        public int IndexOf<TComparer>(T value)
        {
            return IndexOf(value, new GenericEqualityComparer<T>());
        }
    }

А не, всё верно, не компиллируется нифига.

Кароч.
Именно из-за нетипизированной природы параметрического полиморфизма в предлагаемом МНЕ примере-аргументе мы НЕ МОЖЕМ вызывать методы типа T в теле методов MyList<T>.

Ву а ля? Или еще нет?

Но фиг с ним, это всё банальности и я в шоке, что их потребовалось расписать настолько подробно на 15-й год существования дотнета. Дело не только в этом. Различная null-default(T) семантика value и ref типов накладывает свои дополнительные ограничения и тоже резко сужает класс алгоритмов, которые можно было бы выразить прямо из Т, без прибегания к технике "словарей операций", которые, цитирую сам себя:

... в концепции дотнетного ООП такая техника выглядит заимствованием из чужеродного ФП.

Т.е., те фишки ФП, которые не руинят ООП — они в практику дотнета таскаются с удовольствием, смотрю. Остальные практики игнорятся, хотя именно такая реализация параметрического полиморфизма требует именно таких практик.

И я имел ввиду больше вот эти ограничения на разницу в семантике (в одном случае идёт прямая адресация, в другом косвенная), которые не всегда просто преодолеть — оформить непосредственно в виде генерик-кода БЕЗ прибегания к посторонним "словарям операций". Каждый такой словарь — это костыль. В С++ можно обойтись без него, в этом была суть уже моего аргумента. Хотя, можно и с таким же точно костылём — но в С++ хоть есть выбор.

В общем, всё нужное я уже более одного раза говорил ранее...
Просто топик расползся и оно местами сильно по топику раскидано. ))


V>>2. дефолтный компаратор порождается через рефлексию; особенно весело сие после пространных рассуждений коллеги о "безопасной компиляции";

S>Как создается дефолтный компарер — не имеет отношения. Тем более, что он кэшируется.

Т.е., таки, Брут. ))
Имеет в том плане, что может быть создан ТОЛЬКО через рефлексию.
Кеширован или нет — отмазки, это же просто некое инженерное решение-следствие, т.е. уже не принципиально в этом споре.
Более того, само наличие отдельного компаратора, даже для случая встроенных типов — это ой. Потому что в теле самого List<> мы беспомощны.


V>>3. коллега пытался аргументировать об одинаковой работе для случая value-type и ref-type, но приводит такой пример, где методы типа Т не вызываются вовсе, а вызываются методы исключительно ref-типа IComparer<T> (в теле генерик-метода);

S>а методы IEquatable<T> каким образом вызываются? О них ведь речь была.

Методы IEquatable<T> в целевом алгоритме не вызываются никак, даже после Джитта, увы. Вызываются методы черного ящика, причем, исключительно как виртуальные. Т.е., что там на "другой стороне" уже не принципиально.

Т.е., в обсуждаемом примере через "водораздел" ООП-полиморфизма происходит выход на ad hoc полиморфизм. А вот последний может, в свою очередь, может быть реализован и через параметрический полиморфизм и через что угодно. Одно плохо — в системе типов языка последнее невыразимо вообще никак.


V>>Этого коллеге показалось мало и его стало заносить далее: " ты даже на джуниора не потянул бы, ты совершенно не понимаешь происходящего".

V>>Мамая мия.
S>Я полагаю что вы говорили о чем-то разном, подразумевая что об одном и том же.

Я полагаю, что коллега плохо понимает, о чем речь, но обвиняет в плохом понимании окружающих.
Причем, ответвление на vector<> показало вообще кошмар в плане дедуктивных способностей и навыков ведения спора / аргументирования.

Вот тут примерно так же — вместо обсуждения сабжа коллега радостно зацепился за мою фразу "вызов Equals у базового Object", хотя к сути происходящего в методах List<T> оно вообще не имело никакого отношения. Даже само это цепляние было самоподставой (чел повелся на троллинг), ведь в системе типов языка нам доступна только реализация указанного мною ObjectEqualityComparer и я недвусмысленно на это намекал.
Похоже, ты тоже не понял тот "тонкий" троллинг с моей стороны... Но ты-то ладно, это было обсуждение не с тобой, ты не обязан вдумываться в чужие споры.

Кароч, это я уже сам себя веселил, видя полнейшую слепоту оппонента колеги Qbit86.
Просто троллинг был уже нифига не тонкий, вот в чем был самый юмор ситуации, как по мне.

Но все-равно коллега так и не увидел, в чем там собака зарыта... Ну и фиг с ним, значит и не хотел...
Но потом заканчивает своё непонимание рассуждениями о том, что я даже на джуниора не тяну.
Блин, куда катится мир?

На Украине пещерные люди отодвинули грамотных. На форуме тоже порой просто засилье, скажем так, глубоко несообразительных людей... что ваще происходит-то??? )))


V>>В итоге, коллега заслуженно был подвергнут нещадной обструкции.

V>>Причем, весьма мягкой, ИМХО, учитывая происходящее целиком. ))
S>Мягко, но нещадно. Интересно.

Мягкой по форме, нещадной по содержанию. Так бывает. ))
Можно было бы и форму попрямее выбрать, бо это всё просто сюрр для, казалось бы, аж программиста...


V>>Хотя, если упустить весь рисунок развития ситуации, согласен, моя реакция может показаться странной. Там надо на десяток постов вверх подниматься и смотреть на картинку целиком.

S>Смотрел вчера, картина не стоит того.

Я уже высказывал своё восхищение твоими манерами, но нет.

Понимаешь, дело вовсе не в том, что коллега чего-то не понимает.
Невладение какой-то инфой здесь и сейчас — оно ведь совершенно не страшно.
Я бы даже сказал — это полная ерунда, не принципиально ни разу.
Страшно, другое — когда и не хотят владеть.

Еще более страшно, когда оппонент сходу переходит к мелким гадостям — подколкам, язвительности, троллингу и т.д. и т.п. на ровном (на тот момент) месте. С чего бы это, ы?

Вот такие мелкие подлости, да еще от не слишком сообразительного человека — оно приобретает эффект синергии при формировании ответного отношения.

Это же всё личные кач-ва человека, и они тут сверкают просто как россыпь бриллиантов.
В ответ на подобные манеры я обычно включаю свою душевную простоту почти сельского парня, коим и являюсь. ))
Отредактировано 14.02.2017 3:22 vdimas . Предыдущая версия . Еще …
Отредактировано 14.02.2017 3:18 vdimas . Предыдущая версия .
Re[11]: IEquatable<T>
От: vdimas Россия  
Дата: 14.02.17 03:41
Оценка:
Здравствуйте, samius, Вы писали:

S>Смотрел вчера, картина не стоит того.


А не. Почитал рядом непрочитанное ранее.
Смотрю, ничто человеческое тебе тоже не чуждо:

Дада, я вот тоже для тебя западню заготовил, но вот беда (и смешно и обидно вышло... ) переоценил уровень твоего бэкграунда. И ты пролетел мимо этой засады, даже не поморщился. Ну что ж, попробую тебя оттормозить, оттащить назад и все-таки посадить в эту лужу.


Ы-ы-ы, много раз... ))
Re[12]: IEquatable<T>
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.02.17 05:26
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>Я не прав был, что не изучил её (простыню) всю? ))

S>>Сам же и ответил. Не поняв, ЗАЧЕМ, изучил всю, вынес вердикт не о том, о чем была дана ссылка и контекст.

V>Потому что это было уныло — расписывать.

V>Я хорошо понял зачем.
V>Унылость была в том, что коллега не расписал свой аргумент, т.е. отвечать было не нечего, а не на что. Начался отрезок бессмыслицы в обсуждении.

V>Я его просто ткнул носом в слабость его аргумента и удивился потом с того, что коллега даже не понял, во что именно я его ткнул. ))

V>И еще показал, что я подобных флуктуаций его сознания уже ожидал:
V>http://www.rsdn.org/forum/flame.comp/6662410.1

V>Там действительно, лишь флуктуация.

V>Т.е. человек помнит "трюк" насчет ограничений генерик-аргументов, но не помнит, куда и как его можно применять.
Я вот поглядел твои примеры, и у меня ровно такое же впечатление о тебе.
Да, извини что я не на каждую твою фразу отвечаю, уж слишком много!


V>>>Вместо такого фокуса коллега мог назвать конкретный метод конкретного типа и никаких ссылок не надо — кому попервой и даже любопытно, пусть смотрит сам. А остальным, кто еще 12-15 лет назад это всё уже прожевал и выкакал, сорри, тому банально не любопытно глазеть на подобный код.

S>>Коллега понадеялся что контекста обсуждения было достаточно. А в отношении любопытства остальных — согласен. Возможность — юслес на 99% (ИМХО).

V>Коллега не умеет формулировать свои мысли. Если бы он попытался формально расписать свой аргумент, то САМ увидел бы, что его аргумент НЕ канает. Бо в хорошем вопросе содержится половина ответа. И тут как раз тот случай.


V>Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.

А ты не обратил внимания, что между списком в Хаскеле и Eq a тоже нет никакой связи на уровне типов языка?
V>Он ведь правильно пишет (по наитию, скорее):
V>

V>Как он (comparer) там создаётся вообще пофигу.

V>"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.
Какая рефлексия в List<T>?

V>Но оно не пофигу, коль он взялся опровергать вот это:

V>

V>Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.

V>Потому что из-за отсутствия связи на уровне типов в этом месте НЕЛЬЗЯ подать value-type GenericEqualityComparer<T> where T : IEquatable<T>, даже если бы сигнатура метода была примерно такая:
V>
V>class List<T> {
V> public int IndexOf<TComparer>(T value, Comparer comparer) where TComparer : IEqualityComparer<T> {...}
V>...
V>}
V>

V>Т.е. в этом месте можно было бы подать лишь НЕ генерик-реализацию в случае value-type компаратора, т.е. его аргумент аннигилируется без моей помощи. ))
Тебе принципиально впендюривать IndexOf с генериккомпарером внутрь List<T>?

    static class MyExtensions
    {
        public static int IndexOf<T, TComparer>(this IEnumerable<T> source, TComparer comparer)
            where T : IEquatable<T>
            where TComparer : IEqualityComparer<T>
        {
            throw new NotImplementedException();
        }
    }



V>Потому что требуемое ограничение надо было бы распространить выше:

V>
V>class List<T> where T : IEquatable<T>
V>

V>что являлось бы суровым ограничением.
Тут согласен с тем что "являлось бы", но не согласен, что "надо было бы".

V>* Мне приводят пример, где GenericEqualityComparer<T> создаётся через рефлексию, потому что система типов не позволяет указать его явно в исходнике.

Какая разница, как он создается, если он закэширован?

V>* В целевом алгоритме НЕТ никакого трюка по вызову методов целевого типа T.

Указывай ограничение — будет трюк.

V>* Все операции делаются через т.н. "словарь операций", где сам словарь НЕ обязан быть генерик-словарём, там используется обычный ООП-интерфейс.

Я не вижу в этом существенного недостатка.

V>Что в случае специализации в рантайме конкретным value-типом, отличным от Nullable<T2>, например, простым int (не суть важно, просто пример конкретного типа) даст вот такой код:

V>
V>    public override bool Equals(int x, int y)
V>    {
V>       return x.Equals(y);
V>    }
V>


V>Вот ЭТО и есть пример "алгоритма"?

Ну, знаешь. Это пример. А еще у меня году в 2005-м была триангуляция с этим трюком. Исходники не проси, код закрыт режимом.

V>===================

V>Я бы мог всё это дать сразу, но тут сработал такой момент, что когда собеседник "претендует" на некий уровень (а сходу взятый надменно-язвительный тон и регулярное переименование заголовков сообщений в некие "намеки" означает именно это, верно?), то сей "уровень" надо ж уметь поддерживать, не? ))
Т.е. ты не дал, хотя мог, а собеседник должен был дать?

V>В общем, я не должен был всю эту банальщину тут расписывать. Ведь со стороны дотнета выступал не я. А то получается, что я должен был начать сам с собой спорить, бо оппонент за себя не тянет.

Или не хочет.

S>>80% технологий еще древнее. Если не больше.


V>Верно. Поэтому совсем уж заходить на банальности, а тем паче начинать плавать по ним — это банально моветон.

V>Тем более, плавать со "своей стороны баррикад". ))
А с противоположной стороны можно плавать?

V>>>1. там в любом случае происходит вызов метода интерфейса;

S>>Вероятно, но вызов метода интерфейса не через интерфейс там тоже происходит.

V>И ты, Брут?

V>Нет, не происходит.
Так как по-твоему вызываются методы IEquatable<T>?

V>С точки зрения метода IndexOf, мы вызываем методы "черного ящика" — поданного извне словаря операций. Вызовы метода по ограничениям — это уже подробности реализации этого черного ящика и никак не связаны с целевым алгоритмом. Более того, уже показал выше, почему этот "черный ящик" не может иметь генерик-реализацию value-type в системе типов, т.е. у нас тут получаются ДВА независимых разных алгоритма, работающих совместно.

То что ты показал выше — неубедительно. Я не понял, почему не может.

V>Т.е., мы заведомо имеем дело с "нетипизированным параметрическим полиморфизмом".

V>Подробно я описывал тут: http://www.rsdn.org/forum/flame.comp/6680620.1
А куда делся IEquatable<T>? Он ведь обеспечивает типизированность.

V>Блин, ну вот целиком пример (заставляете тратить время на запуск Студии, бо я уже и сам начинаю сомневаться, ы-ы-ы):

V>
V>    class MyList<T>
V>    {
V>        public int IndexOf<TComparer>(T value, TComparer comparer) where TComparer : IEqualityComparer<T>
V>        {
V>            return 0; // заглушка
V>        }

V>        // Не компиллируется! 
V>        public int IndexOf<TComparer>(T value)
V>        {
V>            return IndexOf(value, new GenericEqualityComparer<T>());
V>        }
V>    }
V>

V>А не, всё верно, не компиллируется нифига.
Ты ведь выше сам написал, что нужно добавить ограничение на MyList<T>. Но это если тебе надо IndexOf иметь именно в нем. Нафига — не понятно.

V>Кароч.

V>Именно из-за нетипизированной природы параметрического полиморфизма в предлагаемом МНЕ примере-аргументе мы НЕ МОЖЕМ вызывать методы типа T в теле методов MyList<T>.
А надо вообще?

V>Ву а ля? Или еще нет?

Да как-то мимо и не по делу. Вот в Хаскеле тоже elem никто не пихал в список. И в std::vector нет ничего подобного. Но в C# тебе надо обязательно indexof засунуть в коллекцию, которая не предполагает сравнения элементов. Или ты решил повторить ошибки дизайна коллекции версии 1 и 2?

V>Но фиг с ним, это всё банальности и я в шоке, что их потребовалось расписать настолько подробно на 15-й год существования дотнета. Дело не только в этом. Различная null-default(T) семантика value и ref типов накладывает свои дополнительные ограничения и тоже резко сужает класс алгоритмов, которые можно было бы выразить прямо из Т, без прибегания к технике "словарей операций", которые, цитирую сам себя:

V>

V>... в концепции дотнетного ООП такая техника выглядит заимствованием из чужеродного ФП.

V>Т.е., те фишки ФП, которые не руинят ООП — они в практику дотнета таскаются с удовольствием, смотрю. Остальные практики игнорятся, хотя именно такая реализация параметрического полиморфизма требует именно таких практик.

V>И я имел ввиду больше вот эти ограничения на разницу в семантике (в одном случае идёт прямая адресация, в другом косвенная), которые не всегда просто преодолеть — оформить непосредственно в виде генерик-кода БЕЗ прибегания к посторонним "словарям операций". Каждый такой словарь — это костыль. В С++ можно обойтись без него, в этом была суть уже моего аргумента. Хотя, можно и с таким же точно костылём — но в С++ хоть есть выбор.
В C# тоже есть выбор. Не надо мучить мягкое место через передачу дженерик словарей операций. Интерфейсов достаточно в подавляющем большинстве случаев. Ну а если ты решил сделать Bitmap<T> размером 4KK и хочешь применять на нем свертку с частотой 60Hz, то ты выбрал не тот инструмент.

V>>>2. дефолтный компаратор порождается через рефлексию; особенно весело сие после пространных рассуждений коллеги о "безопасной компиляции";

S>>Как создается дефолтный компарер — не имеет отношения. Тем более, что он кэшируется.

V>Т.е., таки, Брут. ))

V>Имеет в том плане, что может быть создан ТОЛЬКО через рефлексию.
м? А new MyGenericComparer<T>() кто запретил? Тем более, если ты его собрался передавать по значению...
V>Кеширован или нет — отмазки, это же просто некое инженерное решение-следствие, т.е. уже не принципиально в этом споре.
V>Более того, само наличие отдельного компаратора, даже для случая встроенных типов — это ой. Потому что в теле самого List<> мы беспомощны.
Далось тебе его тело.

S>>а методы IEquatable<T> каким образом вызываются? О них ведь речь была.


V>Методы IEquatable<T> в целевом алгоритме не вызываются никак, даже после Джитта, увы. Вызываются методы черного ящика, причем, исключительно как виртуальные. Т.е., что там на "другой стороне" уже не принципиально.

По-твоему там еще и боксинг? Это не соответствует действительности.

V>Т.е., в обсуждаемом примере через "водораздел" ООП-полиморфизма происходит выход на ad hoc полиморфизм. А вот последний может, в свою очередь, может быть реализован и через параметрический полиморфизм и через что угодно. Одно плохо — в системе типов языка последнее невыразимо вообще никак.

Ad hoc через параметрический? Ты бы показал Wadler-у, а то он классы типов вводил, бедолага.


S>>Я полагаю что вы говорили о чем-то разном, подразумевая что об одном и том же.


V>Я полагаю, что коллега плохо понимает, о чем речь, но обвиняет в плохом понимании окружающих.

V>Причем, ответвление на vector<> показало вообще кошмар в плане дедуктивных способностей и навыков ведения спора / аргументирования.

V>Вот тут примерно так же — вместо обсуждения сабжа коллега радостно зацепился за мою фразу "вызов Equals у базового Object", хотя к сути происходящего в методах List<T> оно вообще не имело никакого отношения. Даже само это цепляние было самоподставой (чел повелся на троллинг), ведь в системе типов языка нам доступна только реализация указанного мною ObjectEqualityComparer и я недвусмысленно на это намекал.

V>Похоже, ты тоже не понял тот "тонкий" троллинг с моей стороны... Но ты-то ладно, это было обсуждение не с тобой, ты не обязан вдумываться в чужие споры.
В обсуждении со мной я тоже твой "тонкий" троллинг не понимаю.

V>Кароч, это я уже сам себя веселил, видя полнейшую слепоту оппонента колеги Qbit86.

V>Просто троллинг был уже нифига не тонкий, вот в чем был самый юмор ситуации, как по мне.

V>Но все-равно коллега так и не увидел, в чем там собака зарыта... Ну и фиг с ним, значит и не хотел...

V>Но потом заканчивает своё непонимание рассуждениями о том, что я даже на джуниора не тяну.
V>Блин, куда катится мир?

V>На Украине пещерные люди отодвинули грамотных. На форуме тоже порой просто засилье, скажем так, глубоко несообразительных людей... что ваще происходит-то??? )))

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

V>>>Хотя, если упустить весь рисунок развития ситуации, согласен, моя реакция может показаться странной. Там надо на десяток постов вверх подниматься и смотреть на картинку целиком.

S>>Смотрел вчера, картина не стоит того.

V>Я уже высказывал своё восхищение твоими манерами, но нет.


V>Понимаешь, дело вовсе не в том, что коллега чего-то не понимает.

V>Невладение какой-то инфой здесь и сейчас — оно ведь совершенно не страшно.
V>Я бы даже сказал — это полная ерунда, не принципиально ни разу.
V>Страшно, другое — когда и не хотят владеть.
Тут согласен. Но не могу согласиться что это про Qbit86.

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

Да там еще разобраться бы, кто вперед перешел.

V>Вот такие мелкие подлости, да еще от не слишком сообразительного человека — оно приобретает эффект синергии при формировании ответного отношения.


V>Это же всё личные кач-ва человека, и они тут сверкают просто как россыпь бриллиантов.

V>В ответ на подобные манеры я обычно включаю свою душевную простоту почти сельского парня, коим и являюсь. ))
Так если и ты стараешься соответствовать, какие претензии к собеседникам?
Re[28]: «Собаку съел»
От: vdimas Россия  
Дата: 14.02.17 07:35
Оценка: -1
Здравствуйте, samius, Вы писали:

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

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

Почему бы и нет?
На сегодня существует несколько конкурирующих м/у собой классификаций параметрического полиморфизма, где каждый автор гнёт что-то своё, и?

В любом случае, отсылка к механике выполнения в рантайм при обсуждении системы типов является грубой ошибкой, независимо от степени "теоретической" грамотности автора или его прежних заслуг.

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

ИМХО, во всём этом множестве сценариев, важны лишь следующие координаты:
— монотип или полиморфный тип;
— типизированный полиморфизм или нетипизированный;
— статический матчинг типов к ф-иям (методам) или динамический.

"Типизированный полиморфизм" — это тот самый параметрический полиморфизм в ограничениях (привет обычному ООП-полиморфизму).

А разные авторы, увы, пытаясь зачастую рассуждать о "теоретическом полиморфизме" зачастую рассуждают о тонкостях его реализации в конкретных рекламируемых ими языках программирования (или их тесном семействе от одного корня, типа ML). Это тоже надо помнить при чтении авторов и относится к подобным разлагольствованиям с долей критичности.


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

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

Потому что это эффективней — работать напрямую с монотипами вместо абстракций.

Абстракции, проникающие в рантайм, не бесплатны — почти всегда работа одного и того же машинного кода с разными абстракциями означает работу с "боксированными" значениями, то бишь со ссылочными типами (потому что физический размер ссылки одинаков, независимо от типа, на который ссылка указывает), т.е. везде имеем +1 к косвенности, если машинный код один и тот же.

Например, чтобы заслужить виртуальный вызов в С++, компилятор должен "видеть" ссылочный тип, т.е. видеть не полностью определённый тип (не монотип), а лишь базовый класс (эдакое "ограничение"). Иначе компилятор будет фигачить прямой вызов, вместо виртуального. В Объектном Паскале, Джаве, C# аналогично.

Вот почему с т.з. инженера, а не "голого теоретика" — это грубая ошибка, ссылаться на способ реализации.

Рядом давал уже примеры, когда оптимизатор С++ способен проследить историю возникновения текущего контекста достаточно далеко и зафигачить прямой вызов даже там, где, казалось бы, он совершенно не ожидается. И сразу же появляется возможность порождать ДРУГОЙ машинный код для каждого уникального места, где вызывается одна и та же полиморфная ф-ия.


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

S>Ты не читал и не согласен, или читал но не согласен,

Я-то читал и даже понимал. ))


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


Вполне может быть так, что ты невнимательно прочел по собственной ссылке.

Например, цитата:

In Haskell, this is achieved via the system of type classes and class instances.

Каждый инстанс класса — это ad hoc.
"Инстанс класса" — это объявление перегрузок методов под этот класс.

Но использование техники ограничений на классах типов — это признак (главный и основной) именно т.н. "типизированного параметрического полиморфизма".

Хотя ты, несомненно, из приведенной ниже цитаты сделал ровно противоположный вывод. ))
Спутав, очевидно, сам инстанс со сценарием его использования. Потому что если инстансов меньше двух, то никакого ad hoc нет принципиально, бо нет перегрузки сигнатур.

Далее.
Даже когда мы имеем "одинаковый машинный код" для тех самых боксированных (или ссылочных для ООП) типов, то рано или поздно для вызова специфических для типа действий совершается ad hoc, т.е. матчинг конкретного метода/ф-ии на конкретный тип.

Так вот. Такой матчинг бывает статическим или динамическим. Ввиду того, что в конечном бинарном образе программы на Хаскель система типов всегда является "закрытой" (в отличие от возможностей ООП-полиморфзма, расписанного на базовых абстрактных/полиморфных типах), компилятор способен увидеть, где там происходит выбор перегрузок переопределений для классов типов, а где нет, т.к. банально эта "перегрузка" единственная. В таких случаях, даже если в исходнике у нас использовалась и техника параметрического полиморфизма, и техника ad hoc-специализаций — пофиг, вообще никакого полиморфизма (в отсутствии таких вариаций) в генерируемом коде нет. Ну и плюс оптимизация сводит к похожим сценариям даже те случаи, где перегрузки объективно имеются, но в данном конкретном месте невозможны, т.е. можно считать, что их нет вовсе.


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

S>

S>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.

S>Это по ссылке выше, если что.

ЧТД, недопонимание.
"you can" говорит о возможности, но не обязательности.

Ad hoc — это перегрузка сигнатур. Да, чаще всего мы можем увидеть ad hoc, когда на аргументы накладываются ограничения.
Почему?
Да потому что тогда и только тогда перегрузка и возможна.

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

Вот точный аналог этого примера для C#:
class SomeUtils {
    public bool Elem(List<a> list, a value) where a : IEquatable<a> {...}
}

Это ad hoc или параметрический полиморфизм? ))
Правильный ответ: параметрический.

А так?
class SomeUtils {
    public bool Elem<a>(IList<a> l, a value) where a : IEquatable<a> {...}

    public bool Elem<a, b>(IDictionary<a, b> d, a key) where a : IEquatable<a> {...}
}

Правильный ответ: оба совместно.

Не знаю как тут можно было заплутать...
Ну вот рядом мы как раз обсуждали сценарий "where T : IEquatable<T>" как сценарий параметрического полиморфизма в C#, не?

Еще вопрос — а что ты сможешь сделать затем с b из Maybe b?
Опять точный аналог для C#:
class SomeUtils {
    public Nullable<b> Lookup<a, b>(List<KeyValuePair<a,  b>> list, a key) where a : IEquatable<T> {...}
}

... если до этого в вызывающем контексте вычислений не подал ограничения на b или не указал для на него конкретный тип?
Аж ничего. Не хочешь в этом месте помедитировать?

Собственно, в скипнутом тобой суть вещей раскрыта — про "концепт".
Любой современный типизированный полиморфизм от этого концепта пляшет.

В общем, когда ты начинаешь вызывать одни ф-ии из других, то начинают совместно работать ограничения на полиморфные типы (т.е. классы типов) и/или монотипы + конкурирующие инстансы ф-ий для них (ad doc).

Haskell even allows class instances to be defined for types which are themselves polymorphic (either ad-hoc or parametrically).

Это по ссылке выше, если что.


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


При том, что сам тип a объявлен в этой сигнатуре как параметрически полиморфный?


S>Просто, не правда ли?


Не обманывай себя. ))
Я уже говорил — разные виды полиморфизма работают совместно или даже являются одним и тем же в конкретной ситуации.

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

V>>А тут:

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

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

А тут:
 struct GenericEqualityComparer<T> : IEqualityComparer<T> where T : IEquatable<T>
 {
     public bool Equals(T x, T y)
     {
         if (x != null)
         {
             if (y != null) return x.Equals(y);
             return false;
         }
         if (y != null) return false;
         return true;
     }
 }

?


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

S>да не, я как раз считаю что твое определение equal_to для Хаскеля — это ad hoc.

Даже когда оно одно? ))
Ведь не всегда ограничения вводятся для отличий перегрузок, они часто вводятся для доступа к операциям над "концептом".

Например, аналогичный случай в С++ зовется "частичной специализацией шаблонов", когда на тип можно подать ограничения:
  Пример частичной специализации в ограничениях
// Инфраструктура
using namespace std;

class NotImplemented {};

template<typename T1, typename T2>
struct where
{
    typedef typename enable_if<is_base_of<T2, T1>::value, NotImplemented>::type type;
};

// Использование
template<typename T, typename = NotImplemented>
class List;

template<typename T>
struct IEquatable {
    virtual bool isEqual(const T & other) const = 0;
};

// Определяем List только для наследников IEquatable<T>
template<typename T>
class List<T, typename where<T, IEquatable<T>>::type> {
public:
    void add(T item) {
        list_.push_back(item);
    }

    bool elem(const T & item) const {
        for(auto const & element : list_) {
            if(element.isEqual(item))
                return true;
        }

        return false;
    }

private:
    vector<T> list_;
};

// Пример наследника IEquatable<T>
template<typename T>
struct Box : IEquatable<Box<T>> {
    bool isEqual(const Box<T> & other) const {
        return value == other.value;
    }

    Box(const T & v = T()) : value(v) {}

    T value;
};

// Проверяем
void main() {
    //List<int> list;    // error C2079: 'list' uses undefined class 'List<int,NotImplemented>'
    List<Box<int>> list; // ok

    list.add(42);
    bool elem = list.elem(42);

    cout << elem << endl;
}

Хаскель позволяет трюки подобного рода. C# — нет.


S>И этого не спрятать 10ю обертками equal_to_10 над equal_to_N. Можно попытаться сотней, но я не уверен что получится.


Наоборот, спрятать ad hoc получится с помощью единственной "специализации".

Еще раз. Медленно.
Аргумент в приведенной специализации — параметрически полиморфный.
Несколько конкурирующих специализаций (перегрузок) ф-ии с одним и тем же именем — ad hoc.

Блин, очевидно же, что нельзя создать несколько перегрузок некоей ф-ии (для примера, с одним аргументом), не указав РАЗНЫЕ ограничения на полиморфные типы её аргумента или просто конкретные типы аргументов.

Т.е., если у нас в области видимости есть только одно определение equal_to, то никакого ad hoc не возникает прямо по-определению, потому что для ad hoc-полиморфзма надо минимум две отличающиеся перегрузки одной ф-ии в области видимости.

Но да, наличие специализации для полиморфного аргумента ПОЗВОЛИТ добавлять "конкурирующие" сигнатуры. Тут главное не путать "потенциальную возможность" и "фактическое наличие", как в "you can" по ссылке.

Вот чуть более подробная статья на Хабре:
https://habrahabr.ru/post/166353/

Для объяснения сути ad hoc-полиморфизма был взят пример специализации оператора `+` для разных типов, классов типов и даже списков.
Должно стать чуть понятнее.
Отредактировано 14.02.2017 8:17 vdimas . Предыдущая версия . Еще …
Отредактировано 14.02.2017 8:16 vdimas . Предыдущая версия .
Отредактировано 14.02.2017 8:16 vdimas . Предыдущая версия .
Отредактировано 14.02.2017 8:02 vdimas . Предыдущая версия .
Отредактировано 14.02.2017 7:59 vdimas . Предыдущая версия .
Re[13]: IEquatable<T>
От: vdimas Россия  
Дата: 14.02.17 07:50
Оценка:
Здравствуйте, samius, Вы писали:

V>>Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.

S>А ты не обратил внимания, что между списком в Хаскеле и Eq a тоже нет никакой связи на уровне типов языка?

В Хаскеле эта связь есть через текущий контекст вычислений, когда над каждым типом может выводиться более одного ограничения.
В ФП другая техника, другие принципы декомпозиции.


V>>Он ведь правильно пишет (по наитию, скорее):

V>>

V>>Как он (comparer) там создаётся вообще пофигу.

V>>"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.
S>Какая рефлексия в List<T>?

Рефлексия идёт везде, где в либах используется Comparer<T>.Default.


S>Тебе принципиально впендюривать IndexOf с генериккомпарером внутрь List<T>?


Не понял?
Это отказ от обсуждения систем типов и возможностей параметрического полиморфизма? ))

Ну вот представь, что рефлексия (т.е. хак системы типов) недоступна.
И сразу станет принципиально.
Отредактировано 14.02.2017 7:51 vdimas . Предыдущая версия .
Re[29]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.02.17 16:17
Оценка: +1
Здравствуйте, vdimas, Вы писали:

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


V>>>Хороший теоретик не обязан быть хорошим инженером, и обратное тоже верно.

S>>Т.е у хороших инженеров свой полиморфизм и определения?

V>Почему бы и нет?

V>На сегодня существует несколько конкурирующих м/у собой классификаций параметрического полиморфизма, где каждый автор гнёт что-то своё, и?

Так, может быть, приведешь? Желательно классификации вместе с источниками.

S>>

S>>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.

S>>Это по ссылке выше, если что.

V>ЧТД, недопонимание.

V>"you can" говорит о возможности, но не обязательности.
Конечно о необязательности. Но тут, насколько я понимаю английский — необязательность касается способа определения. Но в независимости от этого способа (можешь в хрустальный шар глядеть), классификация должна быть однозначной.
Так вот, ты согласен что функции elem и lookup ad-hoc полиморфны по типу a? [Да]/[нет]/[согласен, но они параметрические]

Давай сначала с этими двумя позициям разберемся, потом по остальному отвечу.
Re[14]: IEquatable<T>
От: samius Япония http://sams-tricks.blogspot.com
Дата: 14.02.17 16:27
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.

S>>А ты не обратил внимания, что между списком в Хаскеле и Eq a тоже нет никакой связи на уровне типов языка?

V>В Хаскеле эта связь есть через текущий контекст вычислений, когда над каждым типом может выводиться более одного ограничения.

V>В ФП другая техника, другие принципы декомпозиции.

V>>>"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.

S>>Какая рефлексия в List<T>?

V>Рефлексия идёт везде, где в либах используется Comparer<T>.Default.

Если не нравится рефлексия, не используй либы, использующие Comparer<T>.Default. Кто заставляет? Задавай явно свой компарер.


S>>Тебе принципиально впендюривать IndexOf с генериккомпарером внутрь List<T>?


V>Не понял?

V>Это отказ от обсуждения систем типов и возможностей параметрического полиморфизма? ))
List<T> параметрически полиморфен. Что тут еще обсуждать? Но тебе,видимо уже не нужна работающая функция IndexOf с value-type компарером. Тебе IndexOf вкорячить в List<T>, но не добавить ограничение к типу T. Причем, чисто что бы пообсуждать. А мне достаточно внешней к List<T> функции IndexOf. И та нафиг не нужна на самом деле.

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

V>И сразу станет принципиально.
Представил. Ну да, ты ведь полагаешь что как только ты не указал компарер явно и он создался под капотом дядей, то ты обрел параметрический полиморфизм...
Ждем конкурирующие классификации.
Re[15]: IEquatable<T>
От: vdimas Россия  
Дата: 15.02.17 05:35
Оценка:
Здравствуйте, samius, Вы писали:

V>>Рефлексия идёт везде, где в либах используется Comparer<T>.Default.

S>Если не нравится рефлексия

Её просто скоро не будет в свободном доступе. ))
Всё ж к этому идёт.


V>>Это отказ от обсуждения систем типов и возможностей параметрического полиморфизма? ))

S>List<T> параметрически полиморфен. Что тут еще обсуждать?

Обсуждалась система типов + курьёзы, связанные с т.н. "типизированным параметрическим полиморфизмом", при попытке использовать его в стиле тру-ООП, когда разработчики такой системы типов решают облегчить себе жизнь.
Не работает это...

В общем, я тут больше отвечал тем, кто считает, что в С++ обитает "неполноценный параметрический полиморфизм".

Там, где ты рядом скипнул, содержалась полная инфа относительно вида параметрического полиморфизма в С++ (он имеет вполне определённую классификацию — т.н. "нетипизированный параметрический полиморфизм"), а так же объяснял, как легко и непринуждённо из нетипизированного сделать типизированный, причем, более полноценный, чем "тру параметрический полиморфизм" в дотнете.


S>Но тебе,видимо уже не нужна работающая функция IndexOf с value-type компарером.


Нужна, но это невозможно для ситуации, если речь идёт об автоматически подставляемом компилятором генерик-компараторе. Тут даже не важно, value-type или ref будет этот компаратор. Соответствующий сниппет я уже приводил. Не компиллируется.


S>Тебе IndexOf вкорячить в List<T>, но не добавить ограничение к типу T.


Это не мне. Это системе типов дотнета.
В Хаскель и С++ запросто сделать отдельные специализации для IEquatable<> и для любых других мыслимых "концептов".


S>Причем, чисто что бы пообсуждать.


Разумеется. Как и всем в этой ветке.
Мы делимся наблюдениями, инфой, сравниваем, понимаем, делаем выводы.


S>А мне достаточно внешней к List<T> функции IndexOf. И та нафиг не нужна на самом деле.


Пофиг на конкретно List<T> — это просто хорошо известный тип, на котором удобно показать, как разработчику придётся решать аналогичные задачи, буде они возникнут, ведь "концептом" удобно задавать любой список допустимых операций согласно прикладного сценария.

Речь сугубо о выразительности библиотек, об отсутствиии необходимости плодить ручную работу (клонирование) — рядом приводил уже ссылки на автогенерённый код, повторить ссылки? В общем, с учётом обсуждения рядом Net Native и ограничений на рефлексию — вопрос не праздный.


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

V>>И сразу станет принципиально.
S>Представил.

Кодогенерацию через T4? ))


S>Ну да, ты ведь полагаешь что как только ты не указал компарер явно и он создался под капотом дядей, то ты обрел параметрический полиморфизм...


Да не горячись ты так, тут вопрос простой как 3 копейки: коль в объявления параметрических типов вводятся ограничения-концепты, то необходимо было сделать концепты частью типа. Вот и всё кино.

Тогда можно было бы использовать т.н. "специализацию" (ad hoc), чтобы иметь возможность автоматически распространять ограничения текущего контекста вычислений для низлежащего вызываемого кода.

Сейчас же в дотнете НЕТ никакой возможности распространить такие ограничения дальше.
И не надо защищать систему типов C# только за то, что это C#. Будь объективен.

Речь идёт вот о такой предполагаемой фишке:
class List<T> : IList<T> 
{...}

class List<T> : IList<T> where T : IEquatable<T> 
{...}

Разные типы. Пример совместной работы ad hoc и параметрического полиморфизма (рядом ты тоже малость путал одно с другим).

Или вот о такой:
class List<T> : IList<T> 
{
    public IndexOf(T value) {}

    public IndexOf(T value) where T : IEquatable<T> {}
}

Разные методы, опять совместная работа разных видов полиморфизма.

В Хаскеле доступен второй вариант, в С++ — оба. И это прекрасно решает озвученную проблематику насчет всяких хаков системы типов/рефлексии.

Обрати внимание, что в дотнете последняя техника особо мощно смотрелась бы в сочетании с техникой методов-расширений. Это была бы просто киллер-фича, натурально.

А то сейчас на код методов-расширений порой без слёз не взглянешь, когда они пытаются через рефлексию отделить массив от List<T> и от IEnumarable<T>. Согласен, порой и такое полезно, когда произошло стирание типа аж до IEnumerable<>, но уж в случае более полных специализаций можно было бы подставлять совсем эффективный код.

Ты как раз рядом спрашивал "зачем сводить к ad hoc?" — дык, сугубо ж для эффективности! ))


S>Ждем конкурирующие классификации.


Они уже есть от авторов Хаскеля. В Хаскеле работает т.н. "предикативный/пренексный полиморфизм", совместно с той фишкой, что ограничения на полиморфный аргумент являются частью типа (ес-но!) этого аргумента.

В дотнете ограничения на тип НЕ являются частью типа. Ну вот попытайся ты хаскелистам объяснить, как так у вас вышло, что параметрические аргументы методов или типов навроде `Eq a` и `Num a` с т.з. системы типов неразличимы.
Услышишь много интересного.

В общем, это был ответ тем, кто утверждает, что в C# наблюдается "настоящий типизированный параметрический полиморфизм", а вот в С++ — "ненастоящий". Вот НС любит периодически такое задвигать. ))
Эти люди просто не понимают о чем речь.

=========
Сорри, что целиком озвучил самую первую исходную мысль прямо сейчас именно тебе — не прими лично.
Просто нашел собеседника, которому можно подобное озвучивать и он достоверно поймёт, о чем речь. ))
Считай, блажь такая, чтобы не вещать совсем уж в Космос. ))
Отредактировано 15.02.2017 5:37 vdimas . Предыдущая версия .
Re[30]: «Собаку съел»
От: vdimas Россия  
Дата: 15.02.17 06:04
Оценка:
Здравствуйте, samius, Вы писали:

V>>>>Хороший теоретик не обязан быть хорошим инженером, и обратное тоже верно.

S>>>Т.е у хороших инженеров свой полиморфизм и определения?
V>>Почему бы и нет?
V>>На сегодня существует несколько конкурирующих м/у собой классификаций параметрического полиморфизма, где каждый автор гнёт что-то своё, и?
S>Так, может быть, приведешь? Желательно классификации вместе с источниками.

Ммм... Поработать гуглом, провести систематизацию имеющихся систематизаций?

Это ты мне не поверил, что ле, или всего лишь просишь меня сделать за тебя часть работы?
Ну, если уж совсем возникнут сложности с поиском и ты их признаешь, ОК, на следующей итерации потрачу некоторое время...

(Но, вообще, конкретно я себе подобных замашек не позволяю... хотя позволяю много других, угу... )) )


S>>>Это по ссылке выше, если что.

V>>ЧТД, недопонимание.
V>>"you can" говорит о возможности, но не обязательности.
S>Конечно о необязательности.

Бинго!


S>Но тут, насколько я понимаю английский — необязательность касается способа определения.


Краткость — не всегда сестра таланта. Любые хоть сколько-нибудь полезные статьи о разновидностях полиморфизма — они довольно объемны по объективным причинам. Поэтому, зачастую авторы "кратких обзоров" дают минимум, считая, что любопытный, возникни у него желание, копнёт глубже самостоятельно.

Конкретно в Хаскеле и С++ можно задать ф-ии как без ограничений-концептов, так и с ограничениями. Последнее имеет преимущество перед первыми для системы вывода типов (конкретно в Хаскеле — система Хиндли—Милнера, в С++ — правила поиска перегрузок ф-ий, описанные в Стандарте) и является тем самым ad hoc поверх техники параметрического полиморфизма.


S>Но в независимости от этого способа (можешь в хрустальный шар глядеть), классификация должна быть однозначной.


Увы. ))
Пока что все авторы соглашаются лишь о ранге полиморфизма, тут наблюдается однозначность.
Но внутри 1-го ранга многие авторы "резвятся" по самое небалуй.


S>Так вот, ты согласен что функции elem и lookup ad-hoc полиморфны по типу a? [Да]/[нет]/[согласен, но они параметрические]


А точно ли тебе требуется повторять мою аргументацию? ))
В общем, спасибо за именно этот ответ в такой форме — вот за что я люблю с некоторыми общаться и не люблю с некоторыми остальными!

Отвечу: ad hoc — это наличие конкурирующих специализаций. Это ВЕСЬ мой ответ.

Далее можно сколь угодно тщательно спекулировать насчет необходимости vs достаточности, но, если честно, очень лень.
Всё ж на поверхности...


S>Давай сначала с этими двумя позициям разберемся, потом по остальному отвечу.


Да там нечего "по остальному" отвечать.
Я просто не сразу понял, в чём разногласия и написал местами лишнего раньше...

==========
Давай будем объективными — не всегда сразу может быть понятна система представлений оппонента. Иногда требуется несколько итераций. В процессе этих итераций я умудрялся давать тебе то, что тебе НЕ НАДО было и не давал того, что НАДО. Это нормально... А то некоторые оппоненты доходят до того, что "а вот ты раньше такого не говорил, а теперь даёшь новые вводные, мол, выкручиваешься!".
Отредактировано 15.02.2017 6:07 vdimas . Предыдущая версия . Еще …
Отредактировано 15.02.2017 6:06 vdimas . Предыдущая версия .
Re[10]: Visual C# vs C++. Надо сравнить перспективы.
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 15.02.17 08:35
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>А оно и есть киллер-фича кумулятивно, потому что я могу запустить автоматический рефакторинг на огромном проекте, и с высокой вероятность оно сделает все идеально.


Оно, конечно, в целом-то так, но есть нюансы.
dynamic и рефлексия могут добавить много граблей автоматическому рефакторингу. Да на самом деле, даже "анонимные типы" зачастую ломают автоматический рефакторинг — если, например, идёт выделение метода и объект анонимного типа попадает в параметры — студия этого разрулить сама не может и не предупреждая засовывает параметр в object. Билд при этом ломается — ошибки компиляции.
С уважением, Artem Korneev.
Re[29]: «Собаку съел»
От: Lexey Россия  
Дата: 15.02.17 10:24
Оценка:
Здравствуйте, vdimas, Вы писали:

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

S>>

S>>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.

S>>Это по ссылке выше, если что.

V>ЧТД, недопонимание.

V>"you can" говорит о возможности, но не обязательности.

Действительно, недопонимание. Возможность тут — это возможность из наличия признака сделать вывод. Типа "если видишь A, то можешь утверждать B". Это обычное достаточное условие.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[30]: «Собаку съел»
От: vdimas Россия  
Дата: 15.02.17 11:21
Оценка:
Здравствуйте, Lexey, Вы писали:

V>>"you can" говорит о возможности, но не обязательности.

L>Возможность тут — это возможность из наличия признака сделать вывод. Типа "если видишь A, то можешь утверждать B". Это обычное достаточное условие.

А я знал! (С)

Отвечу: ad hoc — это наличие конкурирующих специализаций. Это ВЕСЬ мой ответ.
Далее можно сколь угодно тщательно спекулировать насчет необходимости vs достаточности, но, если честно, очень лень.


===========
Из Вики:

Ad hoc полиморфизм (в русской литературе чаще всего переводится как «специальный полиморфизм» или «специализированный полиморфизм», хотя оба варианта не всегда верны) поддерживается во многих языках посредством перегрузки функций и методов.


Т.е., ограничения аргумента необходимы для возникновения самой возможности перегрузки ф-ий, но недостаточны, чтобы считаться ad hoc.
Re[11]: Visual C# vs C++. Надо сравнить перспективы.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 15.02.17 14:28
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>dynamic и рефлексия могут добавить много граблей автоматическому рефакторингу.


Ну так не надо много эти вещи использовать.

AK>Да на самом деле, даже "анонимные типы" зачастую ломают автоматический рефакторинг — если, например, идёт выделение метода и объект анонимного типа попадает в параметры — студия этого разрулить сама не может и не предупреждая засовывает параметр в object.


Это ошибка, которую надо фиксить, а не фундаментальная проблема.
AVK Blog
Re[31]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.02.17 17:22
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>На сегодня существует несколько конкурирующих м/у собой классификаций параметрического полиморфизма, где каждый автор гнёт что-то своё, и?

S>>Так, может быть, приведешь? Желательно классификации вместе с источниками.

V>Ммм... Поработать гуглом, провести систематизацию имеющихся систематизаций?


V>Это ты мне не поверил, что ле, или всего лишь просишь меня сделать за тебя часть работы?

V>Ну, если уж совсем возникнут сложности с поиском и ты их признаешь, ОК, на следующей итерации потрачу некоторое время...

V>(Но, вообще, конкретно я себе подобных замашек не позволяю... хотя позволяю много других, угу... )) )


Вот внизу этого же сообщения, на которое я отвечаю, ты как раз пишешь, что

Давай будем объективными — не всегда сразу может быть понятна система представлений оппонента. Иногда требуется несколько итераций. В процессе этих итераций я умудрялся давать тебе то, что тебе НЕ НАДО было и не давал того, что НАДО.

Вот тут как раз тот случай, когда мне не понятна система представлений оппонента. Мне кажется что я не могу за тебя подобрать определение, которым ты пользуешься, из источника, которому ты доверяешь. Ты мне пишешь про несколько конкурирующих, но я вообще не нашел чего-либо, что прямо или косвенно бы не ссылалось на [Strachey 67]. Может, плохо искал. С другой стороны, я не ковырял по узкоспециализированнымм инженерным источникам. Я смотрел википедию, хаскельвики, ТАПЛ, работы Wadler-а и кучу всякого шлака. Как мне понять твою систему представлений? Укажи, хотя бы направление! Систематизацию систематизаций я не прошу.

S>>Но тут, насколько я понимаю английский — необязательность касается способа определения.


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

Вот я копнул, ты копнул — у нас разногласия. Покажи мне любую хоть сколько-нибудь полезную статью о разновидности полиморфизма, исключая те, что я перечислял (в том числе [Strachey 67]).

V>Конкретно в Хаскеле и С++ можно задать ф-ии как без ограничений-концептов, так и с ограничениями. Последнее имеет преимущество перед первыми для системы вывода типов (конкретно в Хаскеле — система Хиндли—Милнера, в С++ — правила поиска перегрузок ф-ий, описанные в Стандарте) и является тем самым ad hoc поверх техники параметрического полиморфизма.

В хаскеле задать без ограничения можно, но ограничение от этого не пропадет. И указанный в хаскельвики способ все равно его обнаружит. Вот, правда, может быть наоборот, что ограничение было указано избыточно. Тогда способ соврет.
Prelude> { id1 :: Eq a => a -> a; id1 = id }
Prelude> :t id1
id1 :: Eq a => a -> a



S>>Но в независимости от этого способа (можешь в хрустальный шар глядеть), классификация должна быть однозначной.


V>Увы. ))

V>Пока что все авторы соглашаются лишь о ранге полиморфизма, тут наблюдается однозначность.
V>Но внутри 1-го ранга многие авторы "резвятся" по самое небалуй.
Хрен с ним с рангом. Давай сначала с ad-hoc-ом разберемся.

S>>Так вот, ты согласен что функции elem и lookup ad-hoc полиморфны по типу a? [Да]/[нет]/[согласен, но они параметрические]


V>А точно ли тебе требуется повторять мою аргументацию? ))

V>В общем, спасибо за именно этот ответ в такой форме — вот за что я люблю с некоторыми общаться и не люблю с некоторыми остальными!

V>Отвечу: ad hoc — это наличие конкурирующих специализаций. Это ВЕСЬ мой ответ.


V>Далее можно сколь угодно тщательно спекулировать насчет необходимости vs достаточности, но, если честно, очень лень.

V>Всё ж на поверхности...
Поверхности у всех разные. На моей поверхности elem и lookup ad-hoc полиморфны. На твоей — я так и не понял из ВСЕГО твоего ответа.


S>>Давай сначала с этими двумя позициям разберемся, потом по остальному отвечу.


V>Да там нечего "по остальному" отвечать.

V>Я просто не сразу понял, в чём разногласия и написал местами лишнего раньше...
Я тут копчу лишь за то, что компараторы, использующие "натуральные" сравнения ad-hoc полиморфны, как и все, что их прямо или косвенно использует. Исключая ФВП, которые используют ad-hoc постольку-поскольку им их явно передали.
Re[31]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.02.17 18:16
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>===========

V>Из Вики:
V>

V>Ad hoc полиморфизм (в русской литературе чаще всего переводится как «специальный полиморфизм» или «специализированный полиморфизм», хотя оба варианта не всегда верны) поддерживается во многих языках посредством перегрузки функций и методов.


V>Т.е., ограничения аргумента необходимы для возникновения самой возможности перегрузки ф-ий, но недостаточны, чтобы считаться ad hoc.

Указание на то, где ad-hoc поддерживается посредством перегрузки функций — не является критерием того, что считать ad-hoc, а что нет. Это лишь пример.

А классификация (по Стрэчи) предыдущим разделом. Там же указано что ограничение типа аргумента классом типа — есть ad-hoc. Правда, немного "менее ad-hoc" по Wadler.
Re[16]: IEquatable<T>
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.02.17 19:44
Оценка:
Здравствуйте, vdimas, Вы писали:

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


S>>Если не нравится рефлексия


V>Её просто скоро не будет в свободном доступе. ))

V>Всё ж к этому идёт.
Что всё? Дотнет нейтив? Ну будет на худой конец компилятор указывать тип компарера. Какая разница? Ad-hoc-а от этого меньше не станет.


V>>>Это отказ от обсуждения систем типов и возможностей параметрического полиморфизма? ))

S>>List<T> параметрически полиморфен. Что тут еще обсуждать?

V>Обсуждалась система типов + курьёзы, связанные с т.н. "типизированным параметрическим полиморфизмом", при попытке использовать его в стиле тру-ООП, когда разработчики такой системы типов решают облегчить себе жизнь.

V>Не работает это...
Твой курьез не сработал. Я написал IndexOf извне класса и система типов пережила это.

V>В общем, я тут больше отвечал тем, кто считает, что в С++ обитает "неполноценный параметрический полиморфизм".

Конечно обитает. И полноценный параметрический там тоже обитает. Причем тут List<T> — не понял.

V>Там, где ты рядом скипнул, содержалась полная инфа относительно вида параметрического полиморфизма в С++ (он имеет вполне определённую классификацию — т.н. "нетипизированный параметрический полиморфизм"), а так же объяснял, как легко и непринуждённо из нетипизированного сделать типизированный, причем, более полноценный, чем "тру параметрический полиморфизм" в дотнете.

С IEquatable ты там кучу кода написал, но од ad-hoc не ушел и к чистому параметрическому не пришел.


S>>Но тебе,видимо уже не нужна работающая функция IndexOf с value-type компарером.


V>Нужна, но это невозможно для ситуации, если речь идёт об автоматически подставляемом компилятором генерик-компараторе. Тут даже не важно, value-type или ref будет этот компаратор. Соответствующий сниппет я уже приводил. Не компиллируется.

Он не компилируется лишь от того, что ты вкорячил его в List<T>, которому не захотел ограничивать T. Если вынести — все компилируется. Но это все равно ad-hoc.


S>>Тебе IndexOf вкорячить в List<T>, но не добавить ограничение к типу T.


V>Это не мне. Это системе типов дотнета.

V>В Хаскель и С++ запросто сделать отдельные специализации для IEquatable<> и для любых других мыслимых "концептов".
Специализации! слово-то какое. Прям — ad-hoc.


S>>А мне достаточно внешней к List<T> функции IndexOf. И та нафиг не нужна на самом деле.


V>Пофиг на конкретно List<T> — это просто хорошо известный тип, на котором удобно показать, как разработчику придётся решать аналогичные задачи, буде они возникнут, ведь "концептом" удобно задавать любой список допустимых операций согласно прикладного сценария.


V>Речь сугубо о выразительности библиотек, об отсутствиии необходимости плодить ручную работу (клонирование) — рядом приводил уже ссылки на автогенерённый код, повторить ссылки? В общем, с учётом обсуждения рядом Net Native и ограничений на рефлексию — вопрос не праздный.

Да уперся ты в рефлексию! Рантайм диспетчеризация в типах не способна изменить классификацию полиморфизма.


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

V>>>И сразу станет принципиально.
S>>Представил.

V>Кодогенерацию через T4? ))

Тоже не повлияет на классификацию

S>>Ну да, ты ведь полагаешь что как только ты не указал компарер явно и он создался под капотом дядей, то ты обрел параметрический полиморфизм...


V>Да не горячись ты так, тут вопрос простой как 3 копейки: коль в объявления параметрических типов вводятся ограничения-концепты, то необходимо было сделать концепты частью типа. Вот и всё кино.


V>Тогда можно было бы использовать т.н. "специализацию" (ad hoc), чтобы иметь возможность автоматически распространять ограничения текущего контекста вычислений для низлежащего вызываемого кода.

Напиши код, плиз. Только подробно, чего ты хочешь добиться, и почему это не получается. Не как с IndexOf.

V>Сейчас же в дотнете НЕТ никакой возможности распространить такие ограничения дальше.

V>И не надо защищать систему типов C# только за то, что это C#. Будь объективен.
Я не защищаю (пока). Я просто понять пока не могу, что не так с IndexOf, который вне списка.

V>Речь идёт вот о такой предполагаемой фишке:

V>
V>class List<T> : IList<T> 
V>{...}

V>class List<T> : IList<T> where T : IEquatable<T> 
V>{...}
V>

V>Разные типы. Пример совместной работы ad hoc и параметрического полиморфизма (рядом ты тоже малость путал одно с другим).
Нету тут совместной работы. Потрял квантор всеобщности у T => нет параметрического полиморфизма. То что получилось — специализация через ограничения. А это ad-hoc.

V>Или вот о такой:

V>
V>class List<T> : IList<T> 
V>{
V>    public IndexOf(T value) {}

V>    public IndexOf(T value) where T : IEquatable<T> {}
V>}
V>

V>Разные методы, опять совместная работа разных видов полиморфизма.
Вынеси метод и все будет.

V>В Хаскеле доступен второй вариант, в С++ — оба. И это прекрасно решает озвученную проблематику насчет всяких хаков системы типов/рефлексии.

В Хаскеле список не тащит ограничений на тип элемента. Вместо этого Хаскель позволяет сделать список инстансом Foldable. А elemIndex как раз определена в отдельном модуле.

V>Обрати внимание, что в дотнете последняя техника особо мощно смотрелась бы в сочетании с техникой методов-расширений. Это была бы просто киллер-фича, натурально.

Я тебе предложил метод расширение IndexOf, но не пойму, что ты от него нос воротишь.

V>А то сейчас на код методов-расширений порой без слёз не взглянешь, когда они пытаются через рефлексию отделить массив от List<T> и от IEnumarable<T>. Согласен, порой и такое полезно, когда произошло стирание типа аж до IEnumerable<>, но уж в случае более полных специализаций можно было бы подставлять совсем эффективный код.

Не понял, где там рефлексия в отделении массива от IEnumerable<T>.

V>Ты как раз рядом спрашивал "зачем сводить к ad hoc?" — дык, сугубо ж для эффективности! ))

Тут согласен.

S>>Ждем конкурирующие классификации.


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

предекативность перепендикулярна. Это просто другой признак, а не другая конкурирующая классификация деления parametric/ad-hoc.

V>В дотнете ограничения на тип НЕ являются частью типа. Ну вот попытайся ты хаскелистам объяснить, как так у вас вышло, что параметрические аргументы методов или типов навроде `Eq a` и `Num a` с т.з. системы типов неразличимы.

V>Услышишь много интересного.
не распарсил

V>В общем, это был ответ тем, кто утверждает, что в C# наблюдается "настоящий типизированный параметрический полиморфизм", а вот в С++ — "ненастоящий". Вот НС любит периодически такое задвигать. ))

V>Эти люди просто не понимают о чем речь.

V>=========

V>Сорри, что целиком озвучил самую первую исходную мысль прямо сейчас именно тебе — не прими лично.
V>Просто нашел собеседника, которому можно подобное озвучивать и он достоверно поймёт, о чем речь. ))
Ошибся, походу. Из того что понял — не во всем согласен. А что не понял, то еще не понял. ))
V>Считай, блажь такая, чтобы не вещать совсем уж в Космос. ))
Re[32]: «Собаку съел»
От: vdimas Россия  
Дата: 15.02.17 23:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Мне кажется что я не могу за тебя подобрать определение, которым ты пользуешься, из источника, которому ты доверяешь.


Я никому не доверяю, только лишь своему пролетарскому чутью. ))

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

Ну и тем более не доверяй Вики. ))

Я вот всё жду, когда вот эту опенсорсную книгу докончат:
https://hott.github.io/book/nightly/hott-online-1075-g3c53219.pdf
а потом переведут на русский.
Этой книге можно верить.
По всей этой теме она пишется наиболее тщательно во всей Истории IT как таковой.
Книгу пишет большая группа авторов.
Книга пишется на гитхабе.
Идет постоянный фидбэк.
Идут "ночные сборки", ревью, баги — всё как положено. ))

Кста, инициатор проекта и его ведущий — наш русский математик.

Согласно неё имеем:
— обычные типы (домен значений);
— "вселенные" типов (набор доменов);
— иерархию вселенных (по признаку включения/пересечения их элементов-доменов);
— функциональные типы (мап входного домена на выходной: A->B);
— зависимые функциональные типы (мап семейства функций + входного домена из некоторой вселенной на конкретную ф-ию; параметрически полиморфные ф-ии — это разновидность зависимых функциональных типов);
— производные типы (типы параметризуются типами);
— зависимые типы (типы параметризуются значениями);

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

В общем, я не думаю, что уже пора собирать и давать ссылки на различные классификации параметрического полиморфизма (я имел ввиду именно их). Я вообще не думаю, что это когда-либо стоить делать кроме как для удовлетворения некоторого любопытства и при обязательном умении посмотреть на всё малость "со стороны".

Конкретно у нас я увидел, что мы пока не можем отделить даже сам параметрический полиморфизм от других разновидностей полиморфизма. И конкретно ты тут не при чем. Я заглянул в Вики, почитал чуть "вглубь" — волосы встают дыбом. Тут на форуме встают еще чаще. ))

И да. Некоторые авторы в запале "прозрения" называют параметрический полиморфизм "истинным полиморфизмом".
В общем случае это не так. В общем случае речь идёт о "зависимом функциональном типе" (упомянут выше).
Усё. Остальное зависит от техник, частностей и т.д.

============
Предлагаю рассмотреть устройство и работу обычного ООП-полиморфизма, поскольку там больше всего городских легенд вокруг простейших вещей.

Итак, начинаем с упомянутой тобой не к ночи Вики:

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

Существует несколько разновидностей полиморфизма. Две наиболее различных из них: это ad hoc полиморфизм и параметрический полиморфизм.

Параметрический полиморфизм подразумевает исполнение одного и того же кода для всех допустимых типов аргументов, тогда как ad hoc полиморфизм подразумевает исполнение потенциально разного кода для каждого типа или подтипа аргумента.

Запомним это определение. Оно верное до тех пор, пока "исполнение" будет означать "исполнение по исходнику", а не по машинным кодам. Где-то я даже встречал "физическое исполнение" и тоже ужасался. )) В книге по ссылке говорится:

A polymorphic function is one which takes a type as one of its arguments, and then acts on elements of that type.

Заметь, и параметрический и ad hoc-полиморфизмы прекрасно подходят под определение.

В первом случае мы напишем единственное тело ф-ии, которое сможет обслуживать, допустим, все типы из данной вселенной.
Во втором случае мы для одной и той же ф-ии напишем несколько версий тел — под разные типы из данной вселенной (или их семейства — подвселенных).

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

Вот тебе совместная работа параметрического полиморфизма и ad hoc.
Но и это не единственный сценарий их взаимодействия.
Идем далее.

А далее вики безбожно противоречит самой себе:

Определение полиморфизма как «один интерфейс — много реализаций», популяризованное Бьерном Страуструпом, относится к ad hoc полиморфизму.
...
Параметрический полиморфизм и динамическая типизация намного существеннее, чем ad hoc полиморфизм, повышают коэффициент повторного использования кода, поскольку определенная единственный раз функция реализует без дублирования заданное поведение для бесконечного множества вновь определяемых типов, удовлетворяющих требуемым в функции условиям.
...
Подтипизация (subtyping), или полиморфизм подтипов (subtype polymorphism), означает, что поведение параметрически полиморфной функции ограничивается множеством типов, ограниченных в иерархию «супертип — подтип».

(Например, если имеются типы Number, Rational и Integer, ограниченные отношениями Number :> Rational и Number :> Integer, то функция, определённая на типе Number, также сможет принять на вход аргументы типов Integer или Rational, и её поведение будет идентичным.)

Кошмар, не правда ли? ))
Ладно бы это были выдержки из разных страниц, но эти противоречивые утверждения я собрал с одной страницы.

Вот почему я не очень люблю давать ссылки и практически никогда их не прошу. Я обычно просто благодарен за новую инфу и сам стараюсь подкидывать просто "чистую инфу". Кому интересно — тот осилит. Потому что Интернет не "не может ошибаться", а ровно наоборот — Интернет почти всегда врёт. Каждый раз брать на себя ответственность за это...

ОК. Берем один из моих примеров выше, заворачиваем в объявление ф-ии:
static class Extensions {
    void Draw(this IEnumerable<Widget> widgets, Context context) {
        foreach(var w in widgets)
            w.Draw(context);
    } 
}

Получаем параметрически полиморфный метод Extensions.Draw, который принимает на вход список полиморфных объектов.

К чему я это? К тому, что вопреки популярным заблуждениям (особенно на этом сайте), "параметрический полиморфизм" — это не только и не столько "шаблоны" и "генерики". Параметрически полиморфна будет любая ф-ия, на которую подаётся переменная полиморфного типа (или производного от такого типа).

Идём далее.
В современном программировании принято такие ф-ии объединять в некую сугубо прикладную группу — в классы/интерфейсы/концепты.

Исходно же, исторически, "параметрический полиморфизм" означал программирование в т.н. "черных ящиках". Как пример можно привести любой динамически-типизированный функциональный язык (раньше были модные).

Далее — у нас есть две основные разновидности такого "ящика":

  • "Типизированный ящик" или т.н. "концепт" — список операций над ящиком задан "заранее".

  • "Нетипизированный ящик" — список операций получается "по факту".

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

    Если же в последнем случае типизация происходит в компайлтайм (т.е. статическая типизация), тогда все "черные ящики" должны быть "выведены" компилятором до монотипов или до других "типизированных концептов". Так работает компилятор С++.

    Именно поэтому мы имеем в С++ статическую типизацию на "нетипизированных черных ящиках" и динамическую типизацию на "типизированных концептах" — т.е. абстрактных/виртуальных методах.
    (тут надо остановиться и попытаться переварить, ы-ы-ы)

    Далее. Т.н. "структурный полиморфизм".
    Доступен частично в стандартном Хаскеле — в языке доступна лишь "открытая" структура типов, этой структурой можно оперировать даже тогда, когда элементами структуры является неизвестный тип (вселенная всех типов или некая подвселенная).

    И совсем хорошо "структурный полиморфизм" доступен в диалекте GHC. Они там ввели "семейства типов" (крайне неудачное наименование, сбивающее с толку, но в терминах Хаскеля теперь придётся юзать).

    И точно так же, как в случае классов типов, можно задавать как ad hoc специализации хаскелевских "семейств типов", так и "ограничения" на структуру полиморфных типов (такое ограничение образует собсно "семейство" в терминах Хаскеля, как ограничение на список ф-ий образовывало "класс").

    Любая специализация некоего "семейства" переопределяет "структуру" типа (т.е. конструкцию данных).
    И опять твой викиучебник по Хаскелю пишет:

    Indexed type families, or type families for short, are a Haskell extension supporting ad-hoc overloading of data types.

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

    Потому что чаще всего "семейства типов" определяют в виде "ограничений" не для того, чтобы рядом нарисовать конкурирующее определение для ad hoc, а с целью дать "известную структуру" неизвестному типу. Т.е., представь, что помимо "интерфейсов-ограничений" в дотнете можно было бы указывать "структуры-ограничения" и обращаться к публичным полям типа в теле генерик-методов.

    Возвращаясь к нашим баранам — в С++ структурный полиморфизм доступен: в шаблонах можно обращаться к полям типов. Но этот полиморфизм в C++ тоже идёт не типизированный "изкаробки". (Хотя, есть сразу несколько техник приведения его к типизированному. Например, через т.н. "селекторы" можно сводить структурный полиморфизм к полиморфизму над "концептом", а как последний сделать типизированным в реалиях С++ — уже описывал ранее.)

    ============
    Далее будет совсем смешно (из той же статьи):

    Наследование в С++ реализуется набором ad hoc-механизмов, однако, его использование называется в сообществе языка «полиморфизмом», а сокрытие полей — «абстракцией».

    Каких еще в опу "наборов ad hoc-механизмов"??? Что за потёки сознания? ))
    ad hoc механизм — он один, нет никаких его "наборов".

    И откуда взялось про "в сообществе языка"? У кого там так подгорает-то? ))
    И почему "абстракцией" было названо только лишь сокрытие полей, да еще в обвинительном тоне?
    Прикол, да?
    Принципы абстрагирования родились в IT за пол века до первой версии языка С, не то, что даже С++.

    И уж инкапсуляцию тоже не в С++ придумали как средство абстрагирования.

    Однако, автор на голубом глазу путает "абстрагирование" как способ проектирования публичных интерфейсов (сокрытие частностей), от абстрагирования на уровне системы типов, когда нам такое абстрагирование нужно сугубо для повторного использования кода (чаще всего абстрагирование от конкретного типа за этим и нужно).

    В IT оба этих понятия вокруг одного слова "абстракция" довольно четко отделены уже давно, более 70-ти лет (конец 50-х, начало 60-х 20-го века), но поди ж ты!

    К тому же, любой современный студент знает, что сокрытие полей называется чаще "инкапсуляцией". А когда говорят об "абстракции", то чаще имеют ввиду полиморфизм.


    S>С другой стороны, я не ковырял по узкоспециализированнымм инженерным источникам.


    Ну а я ковырял одно время, пытаясь почерпнуть "знания", угу.
    Был весьма обескуражен вначале, а потом разозлён из-за потраченного времени.

    Поэтому и не спешу никуда никого отсылать на совсем уж "глубокие" исследования. Я пока настойчиво призываю относится к подобным "исследованиям" критически. Бо чем глубже такое исследование, тем оно `уже, тем более ангажирован автор на каком-либо языке программирования и засоряет людям моск ненужными тонкостями отличий кормовой свеклы от брюквы (разновидности одного и того же), разве что в рамках разработанной "самой лучшей в мире классификации параметрического полиморфизма", где на самом почетном месте этой классификации будет рекламируемое чудо, а как же! ))


    S>Вот я копнул, ты копнул — у нас разногласия.


    Ну, у нас возникли совсем уж серьезные разногласия — что есть ad hoc.
    И потребовалось несколько итераций, чтобы ты начал приводить свои источники и я попытался понять, почему ты эти источники понял именно так.

    В общем, тут рассуждения простые. "Поли-" — это много, "морфизм" — приспособляемость (формы — "морфы").

    В случае ad hoc полиморфизма у нас должно быть много подходящих под разные типы (или их групп) определений, а в случае параметрического полиморфизма у нас должно быть такое определение, которое умеет работать на множестве типов.


    S>В хаскеле задать без ограничения можно, но ограничение от этого не пропадет. И указанный в хаскельвики способ все равно его обнаружит. Вот, правда, может быть наоборот, что ограничение было указано избыточно.


    Что значит "указанно избыточно"?
    В смысле, не используется явно в коде ф-ии?
    Но иногда и не надо, ведь есть много "трюков" — например, для конкретного ограничения можно применить некую специфическую логику.
    Суть трюка состоит в том, что мы переносим константы (т.е. некие данные, которые неизменны в течении работы программы) в систему типов, избавляясь от if в теле ф-ий, эксплуатируя имеющуюся систему типов используемого языка, чтобы диспетчеризация происходила "сама".


    S>Хрен с ним с рангом. Давай сначала с ad-hoc-ом разберемся.


    Еще не разобрались? ))


    V>>Отвечу: ad hoc — это наличие конкурирующих специализаций. Это ВЕСЬ мой ответ.

    S>Поверхности у всех разные. На моей поверхности elem и lookup ad-hoc полиморфны. На твоей — я так и не понял из ВСЕГО твоего ответа.

    ОК.
    Оба elem и lookup параметрически полиморфны прямо по определению параметрического полиморфизма. На обе эти ф-ии можно подать аргументы несчетного кол-ва типов. Главное, чтобы такой тип принадлежал вселенной Eq ("классу типов" в терминах Хаскеля).

    Если ты напишешь более одной перегрузки каждой из этих ф-ий, то мн-во этих перегрузок по каждой ф-ии будут составлять ad hoc полиморфизм.


    S>Я тут копчу лишь за то, что компараторы, использующие "натуральные" сравнения ad-hoc полиморфны.


    "Внизу" почти всегда будет ad hoc. ))
    Вон как в примере ф-ии верхнего уровня Draw.
    Само тело ф-ии параметрически полиморфно прямо по определению.
    Но из этого тела через рантайм-диспетчеризацию вызываются ad hoc методы Draw, уникальные для каждого наследника Widget (или группы наследников).


    S>как и все, что их прямо или косвенно использует. Исключая ФВП, которые используют ad-hoc постольку-поскольку им их явно передали.


    Э, нет. Это параметрический полиморфизм распространяется "вверх", т.е. тип, производный от полиморфного, тоже будет полиморфным (например, список полиморфных переменных). В противоположность ему, ad hoc применяется только в конкретном месте, и не распространяется ни вверх, ни вниз. Это просто выбор "по-месту" некоей перегрузки (специализации) из множества их.
  • Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.