DG>>>что и требовалось доказать, что каждый if в коде однозначно задает набор функций аналогичный набору функций при динамической типизации DG>>>соответственно, каждый if в коде образует динамическую типизацию.
VE>>Так с тобой-то я не спорю. Я-то как раз того же мнения. Чтоб либо динамическая типизация — любое ветвление, либо тогда АлгТД тоже не динамическая типизация. Мне же vdimas говорит, что if (x == 0) в Си — не динамическая типизация.
DG>согласен ли ты с утверждением, что статическая типизация: это когда в исходнике if есть (в том или ином виде: ПМ, overloading и т.д.), а в генеренном коде if-а нет?
Только если гарантированно.
DG>вот есть следующий библиотечный код
DG>
DG>type test = Int of int | Float of float | String of string
DG>let dummy_id = function
DG> | Int n -> n
DG> | Float _ -> -1
DG> | String _ -> -2
DG>let dummy2 = function(ienumerable<test> items) = items.Select(item => dummy_id(item)).Sum();
DG>
Я так понимаю, намёк на то, что если мы знаем, что у нас сплошные Int'ы, то мы могли бы не пользовать обобщённый test и тем самым избавиться от лишних проверок? Ну так это надо закодировать в системе типов.
А то иначе это аналогично
struct test
{
int type;
union
{
int x;
float y;
string z;
} value;
};
Здравствуйте, DarkGray, Вы писали:
VE>>А это ещё надо доказать. Связь между интеллектом и сознанием весьма и весьма туманна.
DG>если не ударяться в мистику, то никакого тумана там нет. DG>сознание = способность ставить и решать задачи, а способность ставить и решать задачи определяется способностью применять интеллект (или другими словами, чем выше интеллект, тем более широкий круг задач поддается решению и тем более эффективно они решаются)
Нет. Сознание — это не способность ставить и решать задачи.
Это как раз интеллект.
Сознание лишь информируется о решении задачи (и тогда мы восклицаем "Эврика!", но как именно получено решение — не понимаем) интеллектом.
VE>Я так понимаю, намёк на то, что если мы знаем, что у нас сплошные Int'ы, то мы могли бы не пользовать обобщённый test и тем самым избавиться от лишних проверок?
да
VE> Ну так это надо закодировать в системе типов.
так же намек на то, что такое кодирование явно делать не надо — это лишь приведет к дублированию информации в исходнике, и что такое кодирование может быть выведено автоматически при необходимости, вся информация для этого уже есть в приведенном куске кода.
VE>А то иначе это аналогично VE>
VE>struct test
VE>{
VE> int type;
VE> union
VE> {
VE> int x;
VE> float y;
VE> string z;
VE> } value;
VE>};
VE>
да, это описание аналогичное. вся информация уже есть. Но такое описание требует более сложного и трудоемкого алгоритма, который из такого описания выведет ответ аналогичный предыдущему.
VE>>>А это ещё надо доказать. Связь между интеллектом и сознанием весьма и весьма туманна.
DG>>если не ударяться в мистику, то никакого тумана там нет. DG>>сознание = способность ставить и решать задачи, а способность ставить и решать задачи определяется способностью применять интеллект (или другими словами, чем выше интеллект, тем более широкий круг задач поддается решению и тем более эффективно они решаются)
VE>Нет. Сознание — это не способность ставить и решать задачи. VE>Это как раз интеллект. VE>Сознание лишь информируется о решении задачи (и тогда мы восклицаем "Эврика!", но как именно получено решение — не понимаем) интеллектом.
в русском — сознание используется для определения двух разных явлений:
сознание как синоним осознание/понимание,
сознание как противопоставление подсознанию
ты сейчас скорее говоришь о второй трактовке, я же говорил о первой трактовке
VE>Сознание лишь информируется о решении задачи (и тогда мы восклицаем "Эврика!", но как именно получено решение — не понимаем) интеллектом.
эта фраза подразумевает, что мозг с точки зрения операции "решение задач" можно декомпозировать на независимые друг от друга части: сознание и интеллект.
в рамках какой декомпозиции это возможно?
DM>Я не вижу оснований считать систему типов подобным понятием. Это такая же определябельная конструкция, как группа, кольцо, моноид, коалгебра и т.д.
вот только type system и группа(моноид, кольцо и т.д.) соотносятся также как цвет и красный(зеленый, синий и т.д.)
при этом цвет является аксиоматическим понятием, а красный является определяемым понятием
Здравствуйте, DarkGray, Вы писали:
VE>>Нет. Сознание — это не способность ставить и решать задачи. VE>>Это как раз интеллект. VE>>Сознание лишь информируется о решении задачи (и тогда мы восклицаем "Эврика!", но как именно получено решение — не понимаем) интеллектом.
DG>в русском — сознание используется для определения двух разных явлений: DG>сознание как синоним осознание/понимание, DG>сознание как противопоставление подсознанию
DG>ты сейчас скорее говоришь о второй трактовке, я же говорил о первой трактовке
Нет, о первой.
Вот интересная статья по теме. Собственно, из статьи интересно то, чем сознание не является.
Изначальную постановку задачи осуществляет подсознание. Сознание, при неспособности решить задачу, формирует запрос к интеллекту, который уже решает задачу. При этом для автоматизированных задач не нужно сознание, а для простых (не требующих поиска закономерностей), — не нужен интеллект.
Интеллект — способность находить закономерности и проверять их. Сознание определяется интроспективностью, т.е. моделированием себя. Подсознание определяет инстинктивные интересы.
Уж кому кому, а программистам должно быть известно то забавное обстоятельство, что, порой, усиленно думая над особенно сложной проблемой, решения мы найти никак не можем, но стоит пойти прогуляться, как решение может настигнуть в самый неожиданный момент, главное при этом находиться в некоем режиме поиска решения, но не осознанного, ибо на деле мы можем вообще заниматься чем-либо другим. Можно вспомнить того же доктора Хауса, где в каждой серии неизменно его осеняет вовсе не тогда, когда он напряжённо перебирает варианты. И это вполне себе типично. Интеллект, отделённый от сознания, решил поставленную сознанием задачу, и уведомил об этом. В свою очередь сознание, пользуясь решением интеллекта, формирует решение для подсознание по удовлетворению инстинкта.
То, что подсознание обращается к сознанию, сомнения не вызывает. Как только автоматика попадает в исключительную ситуацию (по пути встретилась лужа), она бесцеремонно прерывает вашу беседу с товарищем и требует немедленного принятия решения, как эту лужу обойти. Однако интеллект тут не нужен, достаточно примитивной оценки. Интеллект задействуется при сложных задачах по поиску закономерностей. И если человек дурак, то он может с неделю смотреть на задачу, как баран на новые ворота, но "Эврика!" к нему просто не явится.
Правда, считать ли способность обходить лужи, сознанием, тот ещё вопрос. С одной стороны, у человека именно сознание на это дело прерывается (вспомним, как мы учимся ездить на велосипеде, например, всё сознание сконцентрированно на процессе до тех пор, пока он не будет доведён до автоматизма), с другой стороны самосознание, вполне возможно, не является необходимым. Под самосознанием скорее понимается способность понимать своё собственное существование. Интеллекту это не нужно для выполнения его функций, подсознанию тоже (это API к инстинктам). Сознание же, как звено между интеллектом и подсознанием, должно уметь переводить задачи с языка подсознания (которое интересуется только приземлёнными инстинктами, т.е. эгоцентрично по своей сути) на язык абстрактного интеллекта, которому как раз на конкретный субъект наплевать; а затем делать перевод обратный, пользуясь плодами абстрактного интеллекта применительно к собственной заднице. А для этого как раз нужно осознавать себя.
VE>Нет, о первой. VE>Вот интересная статья по теме. Собственно, из статьи интересно то, чем сознание не является.
VE>Изначальную постановку задачи осуществляет подсознание. Сознание, при неспособности решить задачу, формирует запрос к интеллекту, который уже решает задачу. При этом для автоматизированных задач не нужно сознание, а для простых (не требующих поиска закономерностей), — не нужен интеллект.
слишком упрощенно.
Например, на текущий момент считается, что невозможно научиться неосознанно точно умножать два десятизначных числа (что является элементарной задачей для калькулятора). Такое умножение можно сделать лишь осознанно в столбик в уме (при сильно развитой кратковременной памяти) или на листке бумаги (если объем кратковременной памяти обычный или меньше).
Другими словами подсознание обособленно от сознания не может решить задачи (даже теоретически), где требуется строгое применение развитого математического аппарата.
VE>Интеллект — способность находить закономерности и проверять их.
это скорее способность больших нейронных сетей, чем способность интеллекта.
При этом такое выделение делается неточно, часто с нарушением законов логики (причинно-следственного аппарат, правильности декомпозиции/композции и т.д.)
Соответственно, сознание необходимо для того, чтобы логическим образом перепроверить гипотезы выдвинутые подсознанием.
VE> Сознание определяется интроспективностью, т.е. моделированием себя. Подсознание определяет инстинктивные интересы.
VE>Уж кому кому, а программистам должно быть известно то забавное обстоятельство, что, порой, усиленно думая над особенно сложной проблемой, решения мы найти никак не можем, но стоит пойти прогуляться, как решение может настигнуть в самый неожиданный момент, главное при этом находиться в некоем режиме поиска решения, но не осознанного, ибо на деле мы можем вообще заниматься чем-либо другим.
да такое явление есть: при снятии осознанного контроля растормаживаются области ответственные за эмиссию догадок(гипотез) несвязанных напрямую с решением задачи.
Но в тоже время есть способы генерить догадки осознанно и более эффективно. Часть методов осознанной генерации догадок рассматривается в том же триз-е, технологиях мозгового штурма и т.д.
зы
как в твоих утверждениях соотносится интеллект и рациональное мышление?
для меня это близкие понятия, при этом я утверждаю, что подсознание плохо "поддерживает" рациональное мышление (в частности, подсознание плохо "поддерживает" строгие логические выводы, строгие математические преобразования и т.д.), соответственно для меня немного дико видеть утверждение, что интеллект "зашит" в подсознание
другими словами, мозг (как всякая нейронная сеть) не может научиться выполнять даже достаточно простые точные алгоритмы.
алгоритм перемножение двух десятичных чисел в столбик требует всего 60 бит на вход, 60 бит доп. памяти и порядка ста шагов(если перемножать в десятичной системе), но мозг не может научиться даже такому простому алгоритму.
Здравствуйте, DarkGray, Вы писали:
DG>слишком упрощенно. DG>Например, на текущий момент считается, что невозможно научиться неосознанно точно умножать два десятизначных числа (что является элементарной задачей для калькулятора). Такое умножение можно сделать лишь осознанно в столбик в уме (при сильно развитой кратковременной памяти) или на листке бумаги (если объем кратковременной памяти обычный или меньше).
Подозреваю, что кратковременная память (та, что оперирует объектами) существует в сознании, а не в подсознании. Перемножение чисел — оперирование объектами.
VE>>Интеллект — способность находить закономерности и проверять их.
DG>это скорее способность больших нейронных сетей, чем способность интеллекта.
Я сужу по тестам на IQ. Все они поголовно (нормальные, которые не имеют отсылке к культуре, т.е. там отсутвует "уберите лишний город" и прочие, там только кружочки-квадратики) — на поиск и проверку закономерностей.
Забавно то, что сами тесты закономерны; один раз разгадав эту закономерность, пациент решает процентов 70-80 задач (простых) мгновенно без привлечения интеллекта, пользуясь уже известной теорией.
DG>Соответственно, сознание необходимо для того, чтобы логическим образом перепроверить гипотезы выдвинутые подсознанием.
Интеллектом. При этом действительно, ощущение, что интеллект сам по себе проверку произвести не способен, а лишь выдаёт найденные закономерности. Далее мы сознательно пытаемся проверить, действительно ли закономерность имеет место быть. Если бы этим занимался интеллект, мы могли бы и не проверять. Тем не менее, нередко интеллект ошибается.
DG>зы DG>как в твоих утверждениях соотносится интеллект и рациональное мышление? DG>для меня это близкие понятия, при этом я утверждаю, что подсознание плохо "поддерживает" рациональное мышление (в частности, подсознание плохо "поддерживает" строгие логические выводы, строгие математические преобразования и т.д.), соответственно для меня немного дико видеть утверждение, что интеллект "зашит" в подсознание
Я не утверждал, что интеллект зашит в подсознание, наоборот, это три разных системы: подсознание, сознание и интеллект. При этом самоосознающая — вторая, так как находится на стыке абстрактной и инстинктивной систем.
Рациональное мышление, то, что механически оперирует логическими утверждениями, — сознание. Причём интеллектуальной работы тут нет — подставлять значения в логические выражения и делать выводы — это примитив. Но из-за ограниченности быстрой памяти и тут делают ошибки.
Интересно то, что плодами сознания может пользоваться подсознание, доведя некоторые действия до автоматики. Тогда при запросе "переключить скорость автомобиля" сознание уже не отвлекается.
При этом сознание, судя по всему, может пользоваться плодами интеллекта. Раз осознав указатели, проблем мы более с ними не испытываем, мы уже можем механически делать утверждения, пользуясь этим понятием. Хотя многие поначалу с трудом могут разобрать, что к чему.
Здравствуйте, DarkGray, Вы писали:
DG>другими словами, мозг (как всякая нейронная сеть) не может научиться выполнять даже достаточно простые точные алгоритмы. DG>алгоритм перемножение двух десятичных чисел в столбик требует всего 60 бит на вход, 60 бит доп. памяти и порядка ста шагов(если перемножать в десятичной системе), но мозг не может научиться даже такому простому алгоритму.
Я пока понимаю это так:
1. Подсознание не умеет оперировать объектами, его действия механические.
Например, переключение скорости заключается в переносе руки в область рычага, захват рычага, перемещение по схеме. Если во время действий происходит сбой, например в руку не поступил сигнал захвата рычага (т.е промахнулись), подсознание прерывает сознание на выполнение необходимых действий.
Получив решение от сознания (многократно), подсознание его может запомнить (механизировать) и пользоваться уже без привлечения сознания.
2. Сознание умеет оперировать объектами, но не может найти способы работы с неизвестными объектами.
Т.е. сознание может применять (мысленно) действия к объектам и т.о. выводить логические суждения. Однако натыкаясь на новый объект, сознание оказывается бессильно. Вступает в дело интеллект.
Получив решение от интеллекта, сознание также может впоследствии пользоваться лишь памятью об объекте и о применимых действиях.
3. Интеллект умеет находить закономерности. В частности, умеет классифицировать объект, или обобщать действия.
Если мы найдём какой-то новый орех, мы его бессильно крутим-вертим, пока нас не осенит, что его можно камнем стукнуть, как другие орехи. Т.е. интеллект то и дело пытается его классифицировать (найти общее с другими объектами). При этом иногда он может выдать нечто неординарное, найдя общее между, казалось бы, несвязанными объектами, и тогда говорят, что человек нестандартно мыслит.
Аналогично интеллект умеет находить общее и между действиями.
Стоит отметить, что даже классификация объекта может исполняться сознанием. Например, мы можем тупо переписать в таблицу свойства нового объекта (цвет, форма и т.п.) и найти общность между новым объектом и теми, что мы знаем. Однако сама способность построения таблиц — продукт работы интеллекта, который научил сознание ими оперировать. Что-то неординарное мы вряд ли таким образом можем найти.
Ко всему прочему сознание имеет возможность учиться и других людей. Мы можем научить человека строить таблицы, выписывать свойства, находить закономерности механически, без привлечения интеллекта.
DG>>другими словами, мозг (как всякая нейронная сеть) не может научиться выполнять даже достаточно простые точные алгоритмы. DG>>алгоритм перемножение двух десятичных чисел в столбик требует всего 60 бит на вход, 60 бит доп. памяти и порядка ста шагов(если перемножать в десятичной системе), но мозг не может научиться даже такому простому алгоритму.
VE>Я пока понимаю это так:
VE>1. Подсознание не умеет оперировать объектами, его действия механические.
по смыслу согласен, хотя формулировка мне не очень нравится
VE>2. Сознание умеет оперировать объектами, но не может найти способы работы с неизвестными объектами.
здесь не согласен. Сознание не умеет так делать лишь пока не знает алгоритма(не придумало и не получило его со стороны), что делать с неизвестным объектом.
Стандартный алгоритм работы с новым объектом:
1)"пошевелить" его: применить к нему все те действия, которые были успешны с другими объектами: подавить, потрясти, понюхать, послушать, попробовать на язык, рассмотреть каждую деталь и т.д. Желательно при этом сначала применять те действия, которые предположительно будут более успешными: дадут больше знания о новом предмете.
2)понаблюдать за результатом каждого действия
3)представить это в виде модели: функций, которые связывают вход (действия) с выходом (как объект менялся в ответ на действие), желательно в виде иерархической декомпозиции
4)связать данную модель с уже имеющимися моделями
5)"зазубрить" модель (опустить ее на подсознательный уровень)
зы
кстати п.1-2 могут опускаться при осознанном обучении, когда читается документация к новому объекту.
п.3 может опускаться, если знания об объекте представлены в виде эффективной модели. к сожалению, большинство документации не содержит в себе описания эффективных моделей объекта, а являются лишь сырой информацией.
VE>3. Интеллект умеет находить закономерности. В частности, умеет классифицировать объект, или обобщать действия. VE>Стоит отметить, что даже классификация объекта может исполняться сознанием.
согласен, если оба пункта объединить: закономерности можно выделять, как неосознанно, так и осознанно.
лучше всего использовать комбинированный подход: сознанием генерить различные картинки (например, используя стат. аппарат, разные способы визуализации информации и т.д., а с помощью подсознания пытаться увидеть в этом закономерности и различия)
VE>Стоит отметить, что даже классификация объекта может исполняться сознанием. Что-то неординарное мы вряд ли таким образом можем найти.
здесь не согласен. опять же мы не можем осознанно найти неординарное только пока не знаем алгоритма по поиску неординарного.
VE>Ко всему прочему сознание имеет возможность учиться и других людей. Мы можем научить человека строить таблицы, выписывать свойства, находить закономерности механически, без привлечения интеллекта.
обучение может быть как неосознанным (так называемый ремесленный подход: подмастерье повторяет все действия за мастером),
так и осознанным (так называемый инженерный или научный подход: знания поднимаются из подсознания и переводятся в форму пригодную для тиражирования, ученик — это знания получает, состыковывает со своим мировозрением и опускает на подсознание)
Здравствуйте, FR, Вы писали:
V>>А если представление в памяти разное, то я процесс приведения неизвестного устройства значения к известному и называю динамической типизацией для случая статически типизированного языка. Чем тебе не нравится приведение ссылочных типов в дотнете, например, или dynamic_cast в С++? Чем же отличается матч АлгТД?
FR>В ПМ (для ML семейства) нет "приведения неизвестного устройства значения к известному" это тупо выбор _заранее_ известных вариантов.
Удивил. Разве это:
"приведения неизвестного устройства значения к известному"
вызвало затруднение в прочтении?
Решил сказать тоже самое своими словами? Или в моем случае известно не настолько _заранее_ насколько у тебя?
Спать надо больше, коллега.
FR>Отличие от dynamic_cast принципиальное в рантайме ПМ ничего ни ищет, ни сравнивает типы, просто банально выполняет switch. FR>Если грубо перевести все на условный си получим:
Скипнул код. В коде ты привел классический union, содержимое которого как раз достоверно неизвестно до проверки метки, назначенной одному из завернутый в union типов.
И да, если это было возражение, то ты забыл нарисовать аналогичный пример с динамической типизацией, скажем, для механики дотнета, выраженной в описании этой механики на том же С. Т.к. я говорил, что это одно и то же, надо было привести обе механики и показать, что это не одно и то же.
Т.е. предположим, код на дотнете примерно такой:
if(type == typeof(Type1)) ...
else if (type == typeof(Type2)) ...
Нарисуй происходящее так же на С, потом сравни с собственным вариантом на switch и попробуй найти принципиальные отличия.
Если найдешь, вернемся к обсуждению... покажу, где у тебя ошибка.
Здравствуйте, VoidEx, Вы писали:
VE>Видимо, абстрактные примеры воспринимаются сложнее, поэтому перейду к конкретике.
Я понятия не имею, где у тебя сложности, если честно. Ты бы попытался сформулировать возражения до примеров. Мало ли, как можно трактовать примеры в разных ситемах типов?
VE>Возьмём CPS-трансформацию, все АлгТД при этом исчезают. Исчезает ли динамическая типизация?
В твоих примерах — ес-но. А ты не ты сам не увидел?
VE>1. Простой if-else
1. VE>
VE>readFromConsole :: IO (Either Int String)
VE>readFromConsole = do
VE> x <- ...
VE> if x then Left 10 else Right "bar"
VE>test = do
VE> v <- readFromConsole
VE> case v of
VE> Left x -> foo x
VE> Right s -> bar s
VE>
2. VE>
VE>readFromConsole :: (Int -> IO r) -> (String -> IO r) -> IO ()
VE>readFromConsole left right = do
VE> x <- ...
VE> if x then left 10 else right "bar"
VE>test = readFromConsole foo bar
VE>
Ну? Сам уже понял? Отличные ведь примеры.
В первом случае ты слил в "бутылочное горлышко" АТД, т.е. потерял информацию о конкретном типе, затем ты "разлил из бутылочного горлышка" обратно, протестировав признак типа. А во втором случае вызвал целевые ф-ии ДО потери информации о конкретном типе.
Аналоги в дотнете, если тебе так будет понятней:
1.
object readFromConsole() {
bool x = ...
if(x) return 10; else return"bar";
}
void test() {
object v = readFromConsole();
if(v is int) foo((int)v);
else if(v is string) bar((string)v);
}
Аналог с той разницей, что object — это условно такой АТД, который объединяет всё мн-во типов дотнета, наследников object. Или можно взять какую-нить sealed-иерархию, чтобы ограничить мощность варианта в точности как в примере до {int, string}, но для сути примера это было вовсе не обязательно.
Здравствуйте, DarkGray, Вы писали:
DG>>позже я специально подчеркнул что я рассматриваю вариант, когда длина массивов и значения не известны на момент компиляции, а появляются в runtime-е.
DM>>Тогда кроме инлайнинга и кое-какого fusion'a (удаления промежуточных массивов или списков) там ничего ненаоптимизируешь.
DG>вот есть следующий библиотечный код DG>let dummy2 = function(ienumerable<test> items) = items.Select(item => dummy_id(item)).Sum(); DG>и стоит задача написать(сгенерить) функцию main, которая на вход принимает последовательность байт (с возможностью random-доступа) вида: DG>
network-int32 len;
последовательность<длина len, тип элемента network-int32> int-array;
network-int32 len2;
последовательность<длина len2, элемент float(4байта)> float-array;
...
DG>и выводит на консоль результат:
Стоп-стоп, ты выше ясно сказал, что значения не известны на момент компиляции. Т.е. мы не знаем, что в каком-то массиве будут только инты.
Дальше, ты тут предполагаешь, что компилятор может угадать и вставить неявное преобразование int -> test вида fun x -> Int x.
Но в любом приличном языке это ошибка, так нельзя. Ведь test мог и так быть определен:
type test = Int1 of int | Int2 of int | Float of float | String of string
В общем виде нет однозначного преобразования int -> test. И даже в нашем частном случае нет оснований считать, что упомянутое выше — то, что нам нужно, а не такое, например:
fun x -> Float (float_of_int (x*3))
Ты отдаешь отчет в том, что для компилятора имена дискриминаторов АлгТД не несут смысла? Что вместо Int of int можно написать Bear of int?
DG>слишком упрощенно. DG>Например, на текущий момент считается, что невозможно научиться неосознанно точно умножать два десятизначных числа (что является элементарной задачей для калькулятора). Такое умножение можно сделать лишь осознанно в столбик в уме (при сильно развитой кратковременной памяти) или на листке бумаги (если объем кратковременной памяти обычный или меньше).
Научиться этому, наверное, невозможно. Но люди, которые могли это делать, науке известны. Вот, например:
В XVIII веке внимание ученых привлекали уникумы-математики или чудо-счетчики, как их еще называют. Одним из таких чудо-счетчиков был Джедедая Бакстон. Он был не только неграмотен, но и глуп, однако мог решать фантастические по сложности математические задачи даже во время разговора или работы. Однажды ему задали такую задачу: сколько денег понадобится, чтобы подковать лошадь ста сорока гвоздями, если один гвоздь стоит один фартинг, второй гвоздь стоит в два раза больше первого, третий в два раза больше второго и т. д.? Бакстон дал (почти правильный) ответ: 725 958 096 074 907 868 531 656 993 638 851 106 фунтов, 2 шиллинга и 8 пенсов. Когда его попросили возвести это число в квадрат (2139), он через два с половиной месяца назвал число, состоявшее из семидесяти восьми цифр. Хотя некоторые подсчеты занимали у Бакстона довольно продолжительное время, они не мешали ему работать, жить жизнью обыкновенного человека.
Обычно уникальные математические способности проявляются в раннем возрасте, когда ребенок почти не имеет практики арифметических вычислений. Естественно, такие способности обнаруживаются не только у аутичных детей. Джордж Паркер Биддер рос здоровым ребенком, но уже в раннем возрасте отличался уникальной способностью решать в уме сложные математические задачи. Так, он мог взять в уме логарифм любого числа с точностью до седьмого-восьмого знака после запятой и определить множители любого большого числа. Едва отец Джорджа убедился в его необыкновенных способностях, он тут же отправился с ним в поездку по Англии и Шотландии. Джордж Биддер (ставший впоследствии инженером-строителем с мировым именем) неоднократно пытался понять процесс, с помощью которого осуществляются сложные вычисления. Однако сначала сумел лишь отметить, что результат вычисления «неожиданно вспыхивает в сознании с быстротой молнии»[162]. Уместно отметить, что и сын Биддера обладал блестящими математическими способностями, хотя и не стал чудо-счетчиком.
Здравствуйте, DarkGray, Вы писали:
DG>если все типы известны при генерации кода (новые типы после генерации не подгружаются, или при подгрузке новых типов происходит перегенерация кода), то dynamic_cast — это тоже банальный switch
То это будет не dynamic_cast, а в нем основной смысл в том что он должен работать и на неизвестных во время компиляции типах и
без поиска по ветке наследования не обойтись.
Здравствуйте, vdimas, Вы писали:
FR>>В ПМ (для ML семейства) нет "приведения неизвестного устройства значения к известному" это тупо выбор _заранее_ известных вариантов.
V>Удивил. Разве это: V>"приведения неизвестного устройства значения к известному" V>вызвало затруднение в прочтении?
Нет.
Затруднения вызывает ваша альтернативная логика в данном вопросе.
Путаете динамическое ветвление и динамическую типизацию.
V>Решил сказать тоже самое своими словами? Или в моем случае известно не настолько _заранее_ насколько у тебя?
В твоем, например в случае dynamic_cast, конечно известно намного меньше.
dynamic_cast производит поиск соответствия в рантайме, успех при этом не гарантирован. В результате получаем указатель через который
можем исполнить код _не известный_ на этапе компиляции (например подгруженная dll).
ПМ ничего ни ищет в рантайме, все возможные пути исполнения и код который будет исполнятся известны заранее, он только передает
управление этим заведомо известным путям исполнения.
V>Скипнул код. В коде ты привел классический union, содержимое которого как раз достоверно неизвестно до проверки метки, назначенной одному из завернутый в union типов.
В случае АлгТД точно также содержимое совершенно достоверно известно до проверки метки. И как в случае union метка, в случае АлгТД
ПМ только актуализирует какой конкретный из заранее известных вариантов выбрать.
V>И да, если это было возражение, то ты забыл нарисовать аналогичный пример с динамической типизацией, скажем, для механики дотнета, выраженной в описании этой механики на том же С. Т.к. я говорил, что это одно и то же, надо было привести обе механики и показать, что это не одно и то же.
В дотнете к сожалению не разбираюсь.
V>Т.е. предположим, код на дотнете примерно такой: V>if(type == typeof(Type1)) ... V>else if (type == typeof(Type2)) ...
Не вижу тут полноценной динамической типизации.
Эмуляцию, притом не полную, ее средствами статики да вижу.
При полной эмуляции у нас типы Type1, Type2 и т. д. заранее не известны и (псевдо)код будет примерно такой:
typetable заполняется в рантайме.
V>Нарисуй происходящее так же на С, потом сравни с собственным вариантом на switch и попробуй найти принципиальные отличия. V>Если найдешь, вернемся к обсуждению... покажу, где у тебя ошибка.
Если брать настоящую динамическую типизацию, то паттерн матчинг я не нарисую, так как его смысл в ней
во многом теряется, вернее он вырождается в некую структурную распаковку, сравнивать которую со статическим
ПМ мало осмысленно.
Если взять такой элементарный динамический код:
def tst(a, b):
a.append(b)
То выполнятся он будет примерно так:
. определяем тип 'a' ищем в его списке методов 'append'
. если не нашли просматриваем всех предков и ищем метод там, если не нашли рантаймное исключение
. если нашли пробуем вызывать подставив 'b' если число аргументов не совпало снова рантаймное исключение
. успешно вызываем 'append'
Здравствуйте, vdimas, Вы писали:
V>Я понятия не имею, где у тебя сложности, если честно. Ты бы попытался сформулировать возражения до примеров. Мало ли, как можно трактовать примеры в разных ситемах типов?
Сложности с тем, что одна и та же программа, но по-разному наложенная на типизацию, в одном случае динамически типизирована, в другом — нет.
И ты вроде с этим соглашаешься, но при этом отрицаешь, что важно не поведение программы (поведение идентично, никаких реинтрпретаций памяти лишних не происходит), а только то, как поверх положена типизация.
VE>>Возьмём CPS-трансформацию, все АлгТД при этом исчезают. Исчезает ли динамическая типизация?
V>В твоих примерах — ес-но. А ты не ты сам не увидел?
Дело в том, что эта трансформация может быть произведена автоматически. Но даже если она не произведена, результирующий код эквивалентен.
При этом в одном случае типизация почему-то динамическая, а в другом — нет.
V>В первом случае ты слил в "бутылочное горлышко" АТД, т.е. потерял информацию о конкретном типе, затем ты "разлил из бутылочного горлышка" обратно, протестировав признак типа. А во втором случае вызвал целевые ф-ии ДО потери информации о конкретном типе.
Только вот код эквивалентен и механически преобразуется один в другой.
V>Аналоги в дотнете, если тебе так будет понятней:
Именно, что не аналоги.
V>1. V>
V>object readFromConsole() {
V> bool x = ...
V> if(x) return 10; else return"bar";
V>}
V>void test() {
V> object v = readFromConsole();
V> if(v is int) foo((int)v);
V> else if(v is string) bar((string)v);
V>}
V>
А если v is MyClass? Где передача MyClass onMyClass? HisClass onHisClass? И так для _всех_ типов.
Именно, что это не аналоги. Как говорится, прочувствуй разницу.
Теперь понял?
V>Аналог с той разницей, что object — это условно такой АТД, который объединяет всё мн-во типов дотнета, наследников object. Или можно взять какую-нить sealed-иерархию, чтобы ограничить мощность варианта в точности как в примере до {int, string}, но для сути примера это было вовсе не обязательно.
Не просто все, а все возможные и все добавляемые в будущем.
V>Еще вопросы?
Конечно. Ты пропустил пример про алгебры, где я убрал ADT вообще.
Любая программа может быть так трансформирована автоматически, ADT при этом исчезают, но программы остаются эквивалентными.
Исчезает ли динамическая типизация?
Внимание, вопрос: исчезает ли она, если код остается прежним, но компилятор внутри проводит такую трансформацию при компиляции?
Здравствуйте, DarkGray, Вы писали:
DM>>>>In computer science, a type system may be defined as "a tractable syntactic framework for classifying phrases according to the kinds of values they compute".
DG>>>, во-вторых: это ужасное определение: определение должно определять понятие через более простые, а в данном случае — определение элементарного понятия "type system" идет через такиие неопределяемые понятия как: syntactic, framework, classifying, phrases, kind, compute, according. DG>>>можно получить строгое формализованное определение всех перечисленных понятий?
Итак, попробую строго сформулировать своими словами. Основной пререквизит для понимания материала — теория множеств, буду исходить из того, что понятие множества и основные операции с ними читателю известны.
1. syntactic framework — это пара множеств (B, R), где B — некоторое множество базовых символов, "терминалов", а R — множество синтаксических правил составления выражений (phrases, термов). Правило диктует форму строящегося выражения, а также содержит множество предусловий на использованные в выражении подвыражения.
2. Phrase, выражение, терм определяется индуктивно:
а) всякий символ из множества терминалов B является термом.
б) результат применения правила из множества R к некоторым термам является термом.
Транзитивное замыкание правил R над B дает множество всех возможных фраз (термов) и определяет некоторый язык (чисто синтаксически).
Важные примеры:
1) B — множество вещественных чисел, R — множество правил вида E+E, E-E, E*E, E/E, (E), с предусловием что Е — выражение. Такая пара нам дает syntactic framework для описания арифметических выражений с числами.
2) B — множество примитивных значений языка ML ((), 0, 1, 2, 3,... 0.0, 0.1,... true, false, "", "a", "aa"...), R — множество правил построения составных значений ( (v,v), Left v, Right v, v + v, v — v...). Такая пара дает syntactic framework для описания языка значений (values).
3) В — множество примитивных типов языка ML (unit, int, float, bool, string...), R — множество правил построения составных типов (T*T, T+T, T -> T...). Получаем язык описания типов, но еще не систему типов, пока это просто язык, грамматика.
3. Пусть L — язык, заданный такой парой (BL,RL). Системой типов для языка L назовем пару (TL, TF), где TL — это некоторый syntactic framework для описания языка типов (TL = (BT,RT), где BT — множество базовых типов, RT — множество правил составления сложных типов), а TF — отображение фраз языка L во фразы языка TL. Оно каждой фразе исходного языка L сопоставляет фразу из языка типов TL, другими словами сопоставляет ей элемент множества всех возможных фраз языка TL. Такое сопоставление и есть classifying, типизация.
Обычно язык типов выбирается так, что каждый тип трактуется как абстракное описание некотрого множества значений. Например, тип int может отвечать за множество целочисленных значений из некоторого диапазона.
Важный нюанс: когда L — язык значений, описывающий возможные рантайм-значения, то процесс сопоставления происходит тоже в рантайме, получается динамическая типизация. Когда L — язык выражений, которые записываются в исходном коде на некотором ЯП, т.е. существуют в виде файла, статически, то процесс сопоставления можно провести без запуска программы, тоже статически, тогда получается статическая типизация.
Еще нюанс: TL может быть подмножеством L. Т.е. некоторые выражения L могут быть описаниями типов.
Отношения с памятью: сама по себе система типов в общем случае не обязана описывать отображение типов на байты в памяти программы. Этот отображение — внутренний вопрос конкретного компилятора или интерпретатора. Разные компиляторы/интепретаторы одного и того же языка могут представлять значения одного и того же типа этого языка в памяти по-разному. Например, тип значение "hello" типа String в языке Руби представлено в памяти по-разному в интепретаторах MRI 1.8, IronRuby и JRuby. Другой пример — значение 42 типа int в языке Окамл представлено в памяти по-разному при компиляции в x86 и x64. Но систему типов это не затрагивает.
Здравствуйте, FR, Вы писали:
FR>Затруднения вызывает ваша альтернативная логика в данном вопросе. FR>Путаете динамическое ветвление и динамическую типизацию.
Не путаю. Я уже говорил, что динамическая типизация — это и есть ветвление, результатом которого является выбор ветки кода для работы с уточненным типом. Сюда же можно отнести предикат, т.е. проверку типа.
FR>В твоем, например в случае dynamic_cast, конечно известно намного меньше. FR>dynamic_cast производит поиск соответствия в рантайме, успех при этом не гарантирован.
Ты сделал сразу две ошибки. Даже если брать твой код, то 1.switch — точно такой же поиск. 2. успех каждой отдельно взятой ветки тоже не гарантирован. А если брать полный аналог на С++, т.е. взять точные типы для сравнения, а не базовые, то для успеха каждой ветки потребуется ровно одно сравнение. Т.е. стоимость будет заведомо идентичная, бо во время dynamic_cast сравниваются адреса vtable, а у АлгТД в Хаскеле сравниваются адреса своей внутренней описательной структуры. Всё 1-к-1-му.
Далее, ты намекаешь — на контроль типов в Хаскеле? И как это связано с механикой? Это всего-лишь встроенный механизм типобезопасности. В С++ и в дотнете без проблем можно породить одноуровневую sealed-иерархию от некоего базового типа, чтобы получить точно такие же гарантии. На суть происходящего это не повлияет.
FR>В результате получаем указатель через который FR>можем исполнить код _не известный_ на этапе компиляции (например подгруженная dll).
Через указатель код исполнить нельзя, можно через таблицу ф-ий, т.е. через адрес ф-ии. В Хаскеле точно так же можно подать адрес неизвестной заранее ф-ии и исполнить.
FR>ПМ ничего ни ищет в рантайме, все возможные пути исполнения и код который будет исполнятся известны заранее, он только передает FR>управление этим заведомо известным путям исполнения.
А почему в С++ не передает заведомо известным путям исполнения? Слишком много предположений, хотя код для сравнения приведен так и не был.
FR>В случае АлгТД точно также содержимое совершенно достоверно известно до проверки метки. И как в случае union метка, в случае АлгТД FR>ПМ только актуализирует какой конкретный из заранее известных вариантов выбрать.
Ну так известно заранее, или надо актуализировать? Определись.
V>>И да, если это было возражение, то ты забыл нарисовать аналогичный пример с динамической типизацией, скажем, для механики дотнета, выраженной в описании этой механики на том же С. Т.к. я говорил, что это одно и то же, надо было привести обе механики и показать, что это не одно и то же.
FR>В дотнете к сожалению не разбираюсь.
Ну хорошо, покажи для Java.
V>>Т.е. предположим, код на дотнете примерно такой: V>>if(type == typeof(Type1)) ... V>>else if (type == typeof(Type2)) ...
FR>Не вижу тут полноценной динамической типизации.
Проверка типов — это одна из операций динамической типизации. Для дотнета, если следом написать приведение типа, то верификатор выкинет лишнюю проверку для этого приведения, т.е. произойдет простое копирование указателя. Вуаля, реинтерпретация памяти успешна:
Type type = obj.GetType();
if(type == typeof(Type1))
foo((Type1)obj);
else if(type == typeof(Type2))
bar((Type2)obj);
FR>Эмуляцию, притом не полную, ее средствами статики да вижу.
Нет, это полная динамика. Но вся динамика сводится к проверке адресов дескрипторов типов, так же как в Хаскеле или С++. 1-в-1.
FR>При полной эмуляции у нас типы Type1, Type2 и т. д. заранее не известны и (псевдо)код будет примерно такой:
Упс. Ты уверен, что понимаешь, что есть динамическая типизация?
FR>typetable заполняется в рантайме.
Она заполняется статически. Даже в случае зависимых модулей, навроде DLL, заполняется линковщиком точно так же, как ресолвятся любые зависимые символы при загрузке DLL, т.е. это такая же статическая зависимость от внешнего символа. На досуге нарисуй цепочку связанных vtable для C++, убедись, в какую сторону идет зависимость (коль повторно говоришь о цепочке наследования). Никогда эти связи не идут от базы к наследникам, т.е. никогда vtable динамически не заполняется, даже при ручной динамической подгрузке DLL.
FR>Если брать настоящую динамическую типизацию, то паттерн матчинг я не нарисую, так как его смысл в ней FR>во многом теряется, вернее он вырождается в некую структурную распаковку, сравнивать которую со статическим FR>ПМ мало осмысленно.
Ничего не понял. Что значит термин "структурная распаковка"? Чем не понравилось "реинтерпретация памяти"?
Я повторюсь, что динамическая типизация в статически компиллируемом языке это следующая 2-х тактная операция:
1. проверка метки типа.
2. реинтерпретация интересующей области памяти согласно метки типа.
В вырожденном случае предиката только п.1, но не суть.
FR>Если взять такой элементарный динамический код:
FR>
FR>def tst(a, b):
FR> a.append(b)
FR>
FR>То выполнятся он будет примерно так:
FR>. определяем тип 'a' ищем в его списке методов 'append' FR>. если не нашли просматриваем всех предков и ищем метод там, если не нашли рантаймное исключение FR>. если нашли пробуем вызывать подставив 'b' если число аргументов не совпало снова рантаймное исключение FR>. успешно вызываем 'append'
Еще раз, речь шла о динамической типизации в статически-типизириуемом языке. Даже если взять твой пример, например, для JS просто ищется мембер append в словаре-объекте. А вот затем уже происходит динамическая типизация, когда проверяется тип мембера append. Сначала выясняется, что это именно ф-ия, причем нужной арности, т.е. происходит реинтерпретация append-object к append-function[1] и только затем вызов. Вся разница с обсуждаемым в том, что в динамических языках эта механика происходит "унутре само", а в статически компилируемом ты должен описать ее явно, через динамическое приведение типов или ПМ.
Потому как объект JS это натуральный АлгТД:
String s | Number n | Function f | Dictionary d.
// JS-Array is Dictionary
И вот внутри этого множества типов работает вся динамическая типизация JS. И происходящее при этом в точности равно происходящему в ПМ на Хаскеле.
Для Схемы и Лиспа аналогично, только кол-во встроенных типов данных чуть больше, а Dictionary замени на Cons. Кстати, исходников простеньких реализаций Лиспа и Схемы дофига, можно взглянуть на происходящее там и убедиться, что я тебя не обманываю — точно такой же switch по меткам типа объектов, как ты привел пример на С сообщением выше.
FR>То есть сплошной поиск никак несводимый к switch.