Re[39]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 18:03
Оценка:
Здравствуйте, alex_public, Вы писали:

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


S>>Я тут вижу только одну проблему. ЧТо ты в одном абзаце снчала говоришь что my_equal_to неявно параметризуется указателем на оператор сравнения для нужного типа, а потом утверждаешь что исходя из необходимости учета машинного кода, выходит что код одинаков. Однако, для разных типов выполняется разный машинный код, именно потому и есть необходимость в указании указателя на оператор сравнения.


_>У тебя похоже какие-то проблемы с пониманием термина "код функции", хотя раньше я что-то не встречал никаких разночтений с ним у других программистов. Точнее с понятием "исходный код функции" у тебя вроде всё нормально, а вот с понятием "машинный код функции" явно какие-то сложности. Потому как ты постоянно приплетаешь машинный код операторов сравнения (совершенно других функций и на уровне исходного и на уровне машинного кода) к my_equal_to.


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

_>1. только изучаемой функции
_>2. всего стека вызовов на полную глубину

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

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

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

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

Так вот, возвращаясь к фиксации (выше я просто подстелил соломку, но в другом месте, не в том, где ты мне яму нарыл): Пирс использует в определении поведение куска кода. Но ты мне предложил лишь два варианта, полагаю что мне нужно выбрать из двух. Я выбираю 2, но с оговоркой. Лишь тот машинный код имеет значение, который влияет на поведение функции. Да, при этом, на всю глубину. Если влияет, то на всю глубину. Если что-то не влияет на поведение — не имеет значение, что там.

_>>>и видим, что следуя твое логике apply — это очевидный ad hoc. Ой. Вот уж действительно повод для криков. )

S>>apply по моей логике — очевидный параметрический полиморфизм. Но apply f — это уже другая функция. И она ad hoc.

_>Где-то в моём примере объявлена или используется функция вида "g = apply f"? ) Не надо подобных дешёвых фокусов.

В том, что касается дешевых фокусов, используя понятие процедурной абстракции, можно верить тому, что поведение функции apply f не отличимо от поведения функции f, и оно же неотличимо от "g = apply f". Если бы это было не так, то функцию apply с аргументом f нельзя было бы использовать вместо функции f. Но ты ее как раз используешь исходя из сохранения поведения. Значит, должен быть удовлетворен любой подстановкой с сохранением его. Если нет — выполняй f сам.

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

S>>Про тела — не скажу. Но одинаковое поведение для разных типов требуется в TAPL (приведу ниже). А твоей my_equal_to очевидно не может обеспечить одинаковое поведение для разных типов. Нужен пример?

_>У my_equal_to абсолютно одинаковое поведение для всех типов — она вызывает (и это вся её деятельность) оператор равенства соответствующего типа.

Ее поведение разное в терминах процедурной абстракции.

S>>Найди здесь хоть какой-то ad hoc. Или нам с тобой надо будет еще рулиться за понимание сочетания слов "абсолютно всегда"?


_>А, ну да) Остроумно. ))) И много таких функций встречается в твоих приложениях? )

О, рад что ты оценил. Да, параметрически полиморфных функций в моих приложениях встречается много.

_>>>Ну вообще говоря мнение из внутреннего мирка Хаскеля при обсуждение глобальных вопросов для меня вообще не аргумент. Но в данном конкретном случае материалы по указанной тобой ссылке опять же противоречит другим твоим позициям. Потому как согласно им apply является параметрически полиморфной. А согласно твоей "кричащей" позиции — нет. )

S>>ты как-то не поймешь все мою позицию, пытаешься выдвигать за меня тезисы. Нет у меня кричащей позиции о том что apply ad hoc. Это ты подставить меня желаешь зачем-то. apply параметрически полиморфна (точка). ad hoc полиморфна apply f, а не apply. Надо объяснять что это разные функции?

_>Функции apply f не существует в природе, пока ты не определил где-то что-то вроде g=apply f. В этом случае на уровне машинных кодов появится отдельная функция с поведение как у apply f, но при этом она будет всего лишь обёрткой над apply.

О, если поведение как у apply f, то я спокоен. Ты ведь все-таки оперириуешь понятием поведение функции? Почему же при словах "поведение куска кода" ты переходишь к исполнителю?

_>>>Это согласно определению из вики Хаскеля. А по твоей позиции (что надо учитывать весь стек вызова) как раз получается ad hoc.

S>>Вообще не получается. Это твои выдумки. Весь стек вызовов функции apply заканчивается на возврате функции, которой ты подашь int или float. И ты либо об этом знаешь, либо никудышный знаток Хаскеля.

_>

_>Ты вот что, серьёзно верил, что каррирование реально существует на уровне машинных кодов? Да если бы кто-то и попытался сделать подобное, то оно работало бы не просто медленно (как нынешний Хаскель), а вообще почти не шевелилось бы (наверное хуже чем какой-нибудь bash).
Ну причем тут "медленно"?

_>https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/FunctionCalls — на вот, просвещайся как обстоят дела в реальности, чтобы не писать больше подобных глупостей.

Вот видишь, согласно понятию процедурной абстракции хаскель может генерить несколько различных тел для одной функции и вызывать их в зависимости от обстоятельств вызова. Сохраняя, при этом поведение, соответствующее execution model. Если завтра технические детали реализации поменяются с "просто медленно" на "вообще почти не шевелилось бы", но сохранится execution model, то на поведение функций apply, f, apply f это не повлияет. Следовательно, сохранится их параметрическая классификация. Будь уверен в этом.

_>>>А я разве где-то писал, что согласен с подобными критериями? ) Данная функция выглядит одинаково для всех типов и в исходных и в машинных кодах. Покажи что конкретно по твоему не укладывается в ней в цитируемое тобой же определение параметрического полиморфизма (например из TAPL).

S>>Ок, давай я его процитирую, что бы под рукой было.
S>>

S>>Parametric polymorphism, the topic of this chapter, allows a single piece of code to be typed “generically,” using variables in place of actual types, and then instantiated with particular types as needed. Parametric definitions are uniform: all of their instances behave the same.

S>>Вот поведение-то и не укаладывается, т.к. оно различное для разных типов. Так же как и различен набор машинных кодов, которые выполнятся (на всю глубину стека) при инстанциации разными типами.

_>Так где тут указано про "всю глубину стека"?

А тут нет глубины стека, т.к. это техдетали реализации.

S>>А вот в это определение:

S>>

S>>Ad-hoc polymorphism, by contrast, allows a polymorphic value to exhibit different behaviors when “viewed” at different types.

S>>твоя my_equal_to абсолютно и полностью укладывается.

_>Не укладывается, т.к. поведение абсолютно одинаковое: вызов оператора равенства для соответствующего типа. )

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

S>>Чую, ответишь что я и Пирса в свою секту перетянул.


_>У меня к его определениям никаких особых возражений нет. Более того, это его абстрактное piece of code как раз в точности соответствует моей формулировке и позволяет сделать два отдельных применения: на уровне исходных кодов (на мой вкус только это и важно) и на уровне машинных кодов (вообще не важно, но можно тоже поанализоровать для развлечения).

Я полагаю что его абстрактное поведение инстансов (кусков кода, параметризованных конкретными типами) употреблено в том же смысле, как и у тебя, когда ты говоришь "с поведение как у apply f, но при этом она будет всего лишь обёрткой" — согласно процедурной абстракции.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.