Re[28]: Каким отладчиком пользовались разработчики Kx System
От: vdimas Россия  
Дата: 24.06.09 00:02
Оценка:
Здравствуйте, thesz, Вы писали:

V>>Придумай куда применить. У нас и констант-то не много в коде обычно, параметры алгоритмов зачастую через конфиги настраиваются в run-time. И не от хорошей жизни.


T>То есть, мы не можем выразить сложность алгоритма через эти самые параметры?


Можем, если захотим. И на С++ подобная фича тоже запросто делается, т.к. параметрами шаблонов могут быть интегральные типы. Просто мне твоя логика не понятна: то ты обвиняешь в "преждевременной оптимизации", то рекламируешь возможность ограничения сложности алгоритмов в контракте. По мне — это противоположные полюсы одного и того же процесса. К тому же, run-time ограничения сложности мне как-то привычнее, ибо они способны оперировать большим числом параметров, например: временем выполнения (что критично для сетевых таймаутов), или текущей мнгновенной загрузкой процессора (была и такая задачка у меня), а подобные параметры не доступны компилятору, естественно. Я потому и попросил тебя привести пример, ибо мой личный опыт мне не подсказал пока killer-example для этой фичи.


T>Один из "косяков" (отсутствие оптимизации случая) не встречался в реальной жизни,


Ты бы на каком-нить форуме архитекторов или QA вот это неосторожное "не встречался в реальной жизни" произнёс, смешали бы с Г моментально. Я уже и так намекал, что такой взгляд несерьёзен, и эдак. В принципе, оставайся при своём.

T>То, что ты их увидел, и то, что ты не хочешь слезать с этого своего коня, меня радует, как ничто другое.


А меня не радует, что мы съехали с основной темы — локализации ошибок. И когда я задаю вопрос, почему в этом случае обещанной помощи компилятора не было (и там есть куда предметно углубиться, поверь), твой ответ "не критично" — это больше чем слив. Это заведомая профанация всего обсуждения. Уже пытался тебя привести в чувство, напомнив, что на конкретных примерах мы обсуждаем _классы_ задач, но всё, к сожалению, мимо. Тем не менее, раз ты настаиваешь, я попытаюсь ниже объяснить, почему в подобных классах задач компилятор не помогает.


T>О, да. Все вокруг либо дети, лиоб уже взрослые, все вокруг либо пишут полную туфту, либо сразу пишут всё, как надо.


Либо делают громкие заявления, которые затрудняются потом объяснить.
"О, да" и иже с ним больше не пиши, это как-то не к лицу разработчикам с таким стажем.

В принципе, тратить время на "философию" я перестал примерно 4-5 лет назад, но периодически непроизвольно рефлексирую на некоторые громкие заявления. Не на все, конечно, а на те, где внутренний наивный оптимизм опять тебе шепчет "а вдруг в этот раз что-то действительно стоящее...". Чаще всего — ан нет, показалось.

T>Итак, строго типизированные представления помогают.


Это известно давно, при чём тут "чистое" ФП? Бывает строго, сильно, слабо типизированные и нетипизированные языки, статически и динамически типизированные, причём, среди функциональных и нефункциональных есть и те и другие. Если же ты имел ввиду статическую типизацию, то опять же, и среди функциональных есть как со статической, так и с динамической типизацией. Скажу больше, алгебраические типы в реализации Хаскеля — это разновидность динамической типизации (не торопись пытаться опровергнуть, это тоже вопрос фундаментального плана).

Разберем, почему в твоем примере не помог коммпилятор (да, в той ситуации это было для тебя не критично... но для меня не критично, что это для тебя не критично , пример-то зрит в корень). Итак. Что суть представляет собой алгебраическая группа? Это некое множество, над которыми определены операции, относящиеся исключительно к членам этого множества. Искать в Хаскеле серебрянную пулю пока бесполезно хотя бы потому, что он позволяет задавать алгебраические множества лишь одного типа — размеченные объединения. Все остальные способы разделения типов на "сорты" выходят за возможности системы типов компилятора (напр. определения группы через предикаты), т.е. не контроллируется в compile-time, а значит, при такой искусственной, с т.з. компилятора декомпозиции, он не помогает с логикой контроля этих "виртуальных" типов. Вот этот твой пример, где не было выхода на другую половину ситуаций (и вообще любой матчинг, где используется аналогичная "глубина просмотра") — всего лишь наглядная демонстрация оперирования группой, св-ва которой невозможно "объяснить" компилятору, потому он и не подсказывает тебе забытый матч, ибо группа нод, содержащих более 2-х близкостоящих констант, существует исключительно в голове разработчика. И ведь, с т.з. теории групп, мы вполне можем задать операции над этой "виртуальной группы", так же как и предикат для определения принадлежности к группе, да вот только статически представить эту группу сложновато, от того оперирование над ней происходит исключительно в рантайм, со всеми вытекающими прелестями. И когда я уже десять раз, наверно, повторял о невозможности компилятора проверять "высокоуровневую логику", ты просто не понимаешь, очевидно, о чём тут идёт речь. А речь тут о том, что пока не придумали того самого "идеального языка", позволяющего задавать произвольные контракты. Была бы возможность задать контракт на такую структуру из нод с константами — и не пропустил бы компилятор твой недописанный матч.


T>Достаточно стандартным приёмом является и конструирование языка для своих внутренних нужд. Даже если это просто некое внутреннее представление.

T>Внутреннее представление есть у всех. Степень типизации, правда, разная.

Во-первых, большинство mainstream языков строго типизированные. Во вторых, конструирование DSL как раз и связано с обсуждаемой проблемой, в саму грамматику DSL и в "компилятор" закладываются ограничения — набор допустимых конструкций, что суть тоже контракт определённого вида. Если рассматривать DSL не для описания данных, а для целей программирования, то большинство из них — это "обрезанные" разновидности существующих ЯП, и в этой "обрезанности" и состоит смысл порождения языка (тебе, как стороннику DSEL персонально), дабы ограничить возможности базового языка до определённого набора безопасных в контексте задачи конструкций. До определённой степени это можно делать на системе типов, но лишь на определённом множестве требований.



T>Вот здесь показано, как пользоваться GADT, чтобы компилятор проверил правильность преобразований.


T>То есть, то, что ghc проверяет в рантайме, простому пользователю ghc доступно во время компиляции, хотя бы и для его нужд поменьше масштабом.

T>Это вынуждает этим пользоваться.
T>Это сокращает количество ошибок.

Пример из твоей личной практики можно?


T>В ghc 6.10.1 появились data families и type families. data families позволяют безопасно преобразовывать данные. Мы можем гарантировать, что входные и выходные данные будут в boxed формате для обычного кода, а все промежуточные — в unboxed для скорости.


"Номер раз", где ты соглашаешься с потенциальной выгодой от гетерогенности.


T>Это используется в реализации OpenCL и Data Parallel Haskell, как я понял из описаний Manuel Chakravarty.

T>В принципе, эти штуки использует факт, что типы данных в Хаскеле по структуре совпадают с выражениями лямбда-исчисления. Над ними можно производить вычисления, как над лямбда-термами.

Здесь не очень понял. В рантайм можно, или все же в compile-time?



T>А я по мелочи — размеры битовых векторов проверяю.


И больше нигде как в ФП это невозможно...


T>Серьёзно. Ну вот откуда ты знаешь, что на ЯП получится хуже, чем на ООЯП? Ты делал сравнительные реализации?


Как я сделаю тебе сравнительную реализацию, если рано или поздно нам приходится упираться в понятие "некопируемого экземпляра"? А если это возможно в ФП через пару приседаний (те же монады), то зачем нам такое ФП? Если нам потребуется модель регистра, то нет ничего естественнее, чем мутабельная переменная.

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


T>А я могу похвастаться тем, что мы делали. ООЯП C++ с мощной библиотекой SystemC проиграл по практически по всем пунктам Хаскелю с одним файликом в двадцать строк кода. В пункты входили быстродействие программы, объём кода, сроки разработки и душевное здоровье членов коллектива.


Суть понятна, без GC некоторые вещи выглядят страшно. Но прикол в том, что на том же C# практически 1-в-1 сделать можно было.
И еще лишь очередное подтверждение банальности, что частный случай проще общего в решении. Т.е., вы сравнивали монстра с 1% процентом его возможностей, а это неспортивно. Я таких сравнений перед каждым новым проектом делаю дофига, если не больше, но далекоидущих выводов не делаю из того факта, что в свободном доступе нет решения, идеально мне подходящего. Где надо — допиливаем, где проще написать самим, чем допилить монтра — пишем своё. (напр, с 0-ля построил серверную библиотеку протокола IAX2 — а этот монстрик далеко не на один файлик, даже не на один десяток). Но ты там на блогах целое шоу из этой будничной ситуации устроил. В общем, много эмоций.

V>>В общем, ты очень много пишешь, но мало приводишь примеров. Из тех, что приводил — не для демонстрации основного твоего посыла "невозможно накосячить", из-за чего собственно и разгорелось у нас. Хотим хлеба и зрелищ. Покажи нам подтверждение своих слов.


T>Ты спрашивай, а не отвечай сам на свои вопросы самым худшим вариантом, что ты смог придумать.


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


...

V>>Где ты увидел вопрос про "плоское пространство имён"? Похоже, ты не отличаешь "область видимости" от "уровня доступа/видимости".


T>Так объясни.


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


V>>И зря ты этот пример привёл, ой как зря. Помнишь спор о графическом представлении программной модели? Вот для как раз этой предметной области графическое представление — самое то. Если интересуешься системами на дискретных событиях, марковскими процессами и прочим, то сразу гоу ту симулинк и не занимайся онанизмом на текстовом ЯП.


T>И ежегодно выкладывай мою годовую зарплату за это удовольствие.


T>Я уж лучше потрачу месяц и помучаюсь с ЯП.


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


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


T>Автоматы на алгебраических типах делаются естественней и безопасней, чем на ООП.


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

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


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

T>Я не перфекционист и перфекционистов сторонюсь. перфекционизм и перфекционисты мешают наслаждаться жизнью.


Все еще не понимаю твоего упрямства и несогласия насчет того, что мы рассматривали класс задач и возможности Хаскеля, а не контекст конкретной проблемы. Ты продолжаешь делать вид, что мы обсуждаем ту конкретную задачу. Скажу по большому секрету: в подавляющем большинстве случаев я вступаю в спор из желания выбить из собеседника интересующую информацию. Но из тебя, похоже, ни по доброй воле, ни в провокациях не выбъешь, поэтому я и покинул ЭТОТ спор.

T>Тебя почти полностью оправдывает, что ты привык к разгильдяйству современных ЯП наподобие C++, где тип умножения может иметь никак не связанные параметры и результат, да ещё и производить побочные действия.


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


T>То, что ты не спросил про это, не даёт тебя оправдать полностью. Уж кому-кому, а тебе-то нужно было знать про возможные подводные камни, в том числе и когда типы аргументов и результата умножения одинаковы.



T>У тебя, видимо, ещё не было опыта, когда ты неправильно что-то предполагал. Ты, видимо, никогда не ошибался в своих предположениях.


T>Ну, так поздравляю: ты не так давно что-то предположил и ошибся! Это новый, очень ценный опыт.


Да, именно, через десяток постов узнать, что операция * не перегружаема в Хаскеле — это крайне ценно. Остальным, к сожалению, можно подтереться.


T>Надеюсь, впредь ты будешь что-то предполагать с учётом возможной твоей ошибки. Очень надеюсь.


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


T>Да и вообще, думать наперёд лучше, чем думать опосля.


А толкать банальности, ИМХО, разновидность троллинга. Ты за собеседника не волнуйся, он обязательно думает, просто у него приоритеты могут не как у тебя стоять, и думает он только над тем, что его интересует. Это надо быть, мягко говоря, не совсем практичной личностью, чтобы заботиться о своем форумном "внешнем виде". Большинство [вменяемых] собеседников обычно обсуждают то, что им интересно, но твой характер ведения диалога полностью исключает такую возможность. Тебе своего времени вот на всё, что было выше, не жаль?


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

V>>Так это я неправильно мыслю об оптимизации вообще, или оно тебе в этом конкретном месте не очень надо было? У тебя с логикой вообще как?

T>Опыт gcc показывает, что ты неправильно мыслишь об оптимизации вообще. Это понятно?

T>Да и в этом конкретном случае тоже неправильно мыслишь. Поскольку лично мне это не было нужно.

gcc сливает MS VC++ в плане оптимизации, это понятно? Бестолковые отсылки на "чужой опыт" без малейшего упоминания каких-либо предметных вещей — это бестолковая манера сама по-себе, это понятно?

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


T>Оная someProp на Хаскеле содержала бы _value в качестве составной части результата. Ты бы смог её протестировать отдельно, на всех интересных входных данных.


Мы не тестируем каждый метод get/set, думаю, ты тоже не тестируешь зажачи аналогичной "сложности". А поинт был в том, что от замыливания глаза мало что спасет.


V>>Или взять твой пример BallinF, там ведь в правой части каждой строки матчинга можно допустить описку/ошибку логики, которая прекрасно скомпилится. И где тут будет помощь компилятора?


T>В Хаскеле — мало. Хотя я тут навострился применять семейства типов, кое-что полезное ловится.


T>В теории типов ты можешь задать (почти) произвольный инвариант в типе. Например, если должно быть сложение на (EBin Plus a b), то нельзя делать вычитания.



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


Я ВСЕГДА крайне внимательно читаю оппонента, собсно за этим и встреваю. Но не всегда способен за оппонента додумывать. А насчет предположения наихудшего варианта — ты уже не первый раз на это жалуешься, но это малость смешно. Я, как находящийся в оппозиции по обсуждаемому вопросу, именно и должен искать слабые места, и лично мне так же интересны в первую очередь наихудшие случаи. Просто ситуация такова, что Хаскель в одних аспектах хорош, в других явно так себе, а лет мне уже достаточно, но времени — ровно наоборот...


T>За исключением прозрачности по ссылкам. И скрытости. Так что это не обычное lvalue.


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


T>>>Типобезопасность в ленивых ФЯ достигается проще всех остальных. Все остальные системы сложнее. BitC, например — авторы сами признают, что задача у них очень мощная и почти неподъёмная.

V>>Наверно ты хотел сказать — вывод типов в ленивых ФЯ достигается проще всех остальных. Однако, ты же можешь и явно типы специфицировать, начиная от примитивных, типа int (или как они там в Хаскель называются). И тогда ленивость/нелинивость будут до фени.

T>Я сказал ровно то, что я хотел сказать. Это не то, что ты считаешь, что я, наверное, сказал.


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


T>Похоже, ты вообще не утруждаешь себя размышлениями. Что будет означать (just nothing list) в сравнении с образцом? nothing — это конструктор, или переменная? Над Хаскелем изначально работали люди, которых приглашают специально поработать над C# или Java, чтобы решить очередные проблемы. Приглашают потому, что они overqualified для работы на полную ставку.


Угу, только сам автор Хаскеля выдвинул несколько иную версию произошедшего.

T>>>Увы, практика доказывает обратное.

T>>>Алгоритм W (Хиндли-Милнера) сперва доказали для чистого подмножества ML, а потом отдельно доказывали для ML со ссылками.
V>>Насколько я понял, еще в конце 80-х все эти вещи произошли.

T>Алгоритм W — 1978. А со ссылками позже на несколько лет.


Ну и? Т.е. этап давно пройденный, за чем дело встало? Почему adga2 только сейчас?
Re[29]: Каким отладчиком пользовались разработчики Kx System
От: thesz Россия http://thesz.livejournal.com
Дата: 24.06.09 11:12
Оценка:
Здравствуйте, vdimas, Вы писали:

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


Стоило с тобой согласиться, так ты с темой хрен знает какой давности вылез. Удивительно.

Чего ты до меня докапываешься?

V>>>Придумай куда применить. У нас и констант-то не много в коде обычно, параметры алгоритмов зачастую через конфиги настраиваются в run-time. И не от хорошей жизни.

T>>То есть, мы не можем выразить сложность алгоритма через эти самые параметры?
V>Можем, если захотим. И на С++ подобная фича тоже запросто делается, т.к. параметрами шаблонов могут быть интегральные типы.

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

Пойдём дальше.

Перегрузи в C++ оператор ';', чтобы она протягивала контекст, как в параметризованных монадах.

С перегруженной ';' мы можем считать сложность алгоритма без изменения исходного кода.

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


Это нормальная логика. Если нужна оптимизация или контроль времени, я буду делать оптимизацию или контроль времени. Если мне говорят, что энергичные вычисления лучше всегда, я говорю "преждевременная оптимизация".

V>По мне — это противоположные полюсы одного и того же процесса.


Преждевременная оптимизация не является другим полюсом какого-либо процесса, на одном из полюсов которого находится контроль времени.

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

V>К тому же, run-time ограничения сложности мне как-то привычнее, ибо они способны оперировать большим числом параметров, например: временем выполнения (что критично для сетевых таймаутов), или текущей мнгновенной загрузкой процессора (была и такая задачка у меня), а подобные параметры не доступны компилятору, естественно.


Их можно ввести и добиться формального учёта.

V>Я потому и попросил тебя привести пример, ибо мой личный опыт мне не подсказал пока killer-example для этой фичи.


Для какой фичи? Определения времени выполнения? Так рилтайм приложения из района встраиваемых систем. Там, где можно использовать Atom.

T>>Один из "косяков" (отсутствие оптимизации случая) не встречался в реальной жизни,

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

Ещё раз. Это был мой личный проект, я работал над тем, чего ни у кого не видел. Я работал в ограничениях, которые я сам и установил, я тебе про это уже не раз сказал.

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

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

T>>То, что ты их увидел, и то, что ты не хочешь слезать с этого своего коня, меня радует, как ничто другое.

V>А меня не радует, что мы съехали с основной темы — локализации ошибок. И когда я задаю вопрос, почему в этом случае обещанной помощи компилятора не было (и там есть куда предметно углубиться, поверь), твой ответ "не критично" — это больше чем слив.

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

Смотри на приблизительный сценарий нашей беседы:
T: Вот такая задача, вот так в ней мне помог компилятор...
V: А вот с этим он не помог.
T: С чем не помог?
V: А вот с этим — когда я делал похожее, у меня было вот эдак, и в твоём случае компилятор с этим не помог.
T: Но в моей задаче не было этого!
V: А почему тебе компилятор не помог с этим справиться?
T: Да потому, что в моей задаче это не было критично и я такого не делал!
V: То, что ты говоришь "не критично", означает слив.

Это глупо — требовать от меня, чтобы при решении моей частной задачи компилятор помог мне решить твою частную задачу.

V>Это заведомая профанация всего обсуждения. Уже пытался тебя привести в чувство, напомнив, что на конкретных примерах мы обсуждаем _классы_ задач, но всё, к сожалению, мимо. Тем не менее, раз ты настаиваешь, я попытаюсь ниже объяснить, почему в подобных классах задач компилятор не помогает.


Трепещу в нетерпении.

T>>О, да. Все вокруг либо дети, лиоб уже взрослые, все вокруг либо пишут полную туфту, либо сразу пишут всё, как надо.


V>Либо делают громкие заявления, которые затрудняются потом объяснить.

V>"О, да" и иже с ним больше не пиши, это как-то не к лицу разработчикам с таким стажем.

На всякий случай: "О, да." это цитата из Града Обречённого.

V>В принципе, тратить время на "философию" я перестал примерно 4-5 лет назад, но периодически непроизвольно рефлексирую на некоторые громкие заявления. Не на все, конечно, а на те, где внутренний наивный оптимизм опять тебе шепчет "а вдруг в этот раз что-то действительно стоящее...". Чаще всего — ан нет, показалось.


Ты не даёшь себе труда разобраться.

Я уже встречался с этим шаблоном на примере ЖЖ пользователя lex_kravetski. Он тоже про Хаскель спрашивал. Практически всё, что ему рассказывали, он сводил к "это мы обёрткой сделаем" и "это мы можем в динамике проверить". Практически каждый третий его комментарий заканчивался "и чем это лучше Java?"

Однажды попав в смоляную яму Тьюринга (Turing tar-pit), он не видит разницы между Тьюринг полными языками.

Так и здесь.

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

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

Просто (pardon the pun, it's intented) многие вещи при переходе на алгебраические типы станут выполняться проще настолько, что станут возможными.

T>>Итак, строго типизированные представления помогают.

V>Это известно давно, при чём тут "чистое" ФП? Бывает строго, сильно, слабо типизированные и нетипизированные языки, статически и динамически типизированные, причём, среди функциональных и нефункциональных есть и те и другие. Если же ты имел ввиду статическую типизацию, то опять же, и среди функциональных есть как со статической, так и с динамической типизацией. Скажу больше, алгебраические типы в реализации Хаскеля — это разновидность динамической типизации (не торопись пытаться опровергнуть, это тоже вопрос фундаментального плана).

V>Разберем, почему в твоем примере не помог коммпилятор (да, в той ситуации это было для тебя не критично... но для меня не критично, что это для тебя не критично , пример-то зрит в корень). Итак. Что суть представляет собой алгебраическая группа? Это некое множество, над которыми определены операции, относящиеся исключительно к членам этого множества. Искать в Хаскеле серебрянную пулю пока бесполезно хотя бы потому, что он позволяет задавать алгебраические множества лишь одного типа — размеченные объединения.

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

Классы типов?

V>т.е. не контроллируется в compile-time, а значит, при такой искусственной, с т.з. компилятора декомпозиции, он не помогает с логикой контроля этих "виртуальных" типов. Вот этот твой пример, где не было выхода на другую половину ситуаций (и вообще любой матчинг, где используется аналогичная "глубина просмотра") — всего лишь наглядная демонстрация оперирования группой, св-ва которой невозможно "объяснить" компилятору, потому он и не подсказывает тебе забытый матч, ибо группа нод, содержащих более 2-х близкостоящих констант, существует исключительно в голове разработчика. И ведь, с т.з. теории групп, мы вполне можем задать операции над этой "виртуальной группы", так же как и предикат для определения принадлежности к группе, да вот только статически представить эту группу сложновато, от того оперирование над ней происходит исключительно в рантайм, со всеми вытекающими прелестями.

V>И когда я уже десять раз, наверно, повторял о невозможности компилятора проверять "высокоуровневую логику", ты просто не понимаешь, очевидно, о чём тут идёт речь. А речь тут о том, что пока не придумали того самого "идеального языка", позволяющего задавать произвольные контракты. Была бы возможность задать контракт на такую структуру из нод с константами — и не пропустил бы компилятор твой недописанный матч.

Coq и иже с ними?

T>>Достаточно стандартным приёмом является и конструирование языка для своих внутренних нужд. Даже если это просто некое внутреннее представление.

T>>Внутреннее представление есть у всех. Степень типизации, правда, разная.
V>Во-первых, большинство mainstream языков строго типизированные.

Не с достаточной степенью строгости.

V>Во вторых, конструирование DSL как раз и связано с обсуждаемой проблемой, в саму грамматику DSL и в "компилятор" закладываются ограничения — набор допустимых конструкций, что суть тоже контракт определённого вида. Если рассматривать DSL не для описания данных, а для целей программирования, то большинство из них — это "обрезанные" разновидности существующих ЯП, и в этой "обрезанности" и состоит смысл порождения языка (тебе, как стороннику DSEL персонально), дабы ограничить возможности базового языка до определённого набора безопасных в контексте задачи конструкций. До определённой степени это можно делать на системе типов, но лишь на определённом множестве требований.


Со временем всё более и более широком.

T>>Вот здесь показано, как пользоваться GADT, чтобы компилятор проверил правильность преобразований.

T>>То есть, то, что ghc проверяет в рантайме, простому пользователю ghc доступно во время компиляции, хотя бы и для его нужд поменьше масштабом.
T>>Это вынуждает этим пользоваться.
T>>Это сокращает количество ошибок.
V>Пример из твоей личной практики можно?

Описание команд модели процессора с учётом размеров регистров.

data Expr size v f where
        ...
    EBinary    :: BinOp leftsize rightsize resultsize
           -> Expr leftsize v f -> Expr rightsize v f
           -> Expr resultsize v f
       ...
data BinOp leftsize rightsize resultsize where
    Plus    :: BinOp size size size
    Minus    :: BinOp size size size
    Mul    :: BinOp size size size
    Mul2    :: BinOp size size (NPlus size size)
        ...


T>>В ghc 6.10.1 появились data families и type families. data families позволяют безопасно преобразовывать данные. Мы можем гарантировать, что входные и выходные данные будут в boxed формате для обычного кода, а все промежуточные — в unboxed для скорости.

V>"Номер раз", где ты соглашаешься с потенциальной выгодой от гетерогенности.

Чего?

T>>Это используется в реализации OpenCL и Data Parallel Haskell, как я понял из описаний Manuel Chakravarty.

T>>В принципе, эти штуки использует факт, что типы данных в Хаскеле по структуре совпадают с выражениями лямбда-исчисления. Над ними можно производить вычисления, как над лямбда-термами.
V>Здесь не очень понял. В рантайм можно, или все же в compile-time?

Compile time.

Смотри (применение NPlus смотри выше в BinOp):
data Z = Z
data S n = S n

type family   NPlus a b
type instance NPlus Z a = a
type instance NPlus (S a) b = S (NPlus a b)


T>>А я по мелочи — размеры битовых векторов проверяю.

V>И больше нигде как в ФП это невозможно...

Настолько просто — нет.

T>>Серьёзно. Ну вот откуда ты знаешь, что на ЯП получится хуже, чем на ООЯП? Ты делал сравнительные реализации?

V>Как я сделаю тебе сравнительную реализацию, если рано или поздно нам приходится упираться в понятие "некопируемого экземпляра"?

Что такое "некопируемый экземпляр"?

V>А если это возможно в ФП через пару приседаний (те же монады), то зачем нам такое ФП?

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

Увы, и ах, но нет.

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

В этом случае "мутабельная переменная" здесь не совсем подходит.

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


Буквально одна, конкретно State. А есть ещё Cont, List, Error... А есть ещё их комбинации...

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


Всё равно у меня на выходе функция, а её проще проверять.

Монада состояния это функция state -> (a,state). На любую часть монадического кода я могу подать какое угодно state и проверить, что же за a и что же за state он мне вернёт.

Вырезал, и проверил.

Очень просто.

V>Признаюсь, грамотный ответ именно на этот вопрос интересует больше, чем все другие вместе взятые по теме ФП (ввиду практичности этого момента, в отличии от прочей задвигаемой здесь белеберды о "самоконтроллируемости всего").


Они связаны друг с другом.

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

T>>А я могу похвастаться тем, что мы делали. ООЯП C++ с мощной библиотекой SystemC проиграл по практически по всем пунктам Хаскелю с одним файликом в двадцать строк кода. В пункты входили быстродействие программы, объём кода, сроки разработки и душевное здоровье членов коллектива.


V>Суть понятна, без GC некоторые вещи выглядят страшно. Но прикол в том, что на том же C# практически 1-в-1 сделать можно было.


Не поверю, пока не увижу. Даже странно, что ты не написал те самые 20 строк кода, если всё настолько один-в-один.

V>И еще лишь очередное подтверждение банальности, что частный случай проще общего в решении. Т.е., вы сравнивали монстра с 1% процентом его возможностей, а это неспортивно.


Для Хаскеля на тот момент существовал Hawk, на котором делали много интересных моделей разных устройств. Он, правда, до конца не собирался, но его исходники были доступны.

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

Товарищи, использовавшие SystemC, не смогли провести такой анализ.

Надо отметить, что Bluespec Verilog, что сейчас набирает обороты в индустрии железа, пользуется примерно такой же моделью — тактовых сигналов нет, провода соединять друг с другом нельзя, работаем с битами, а не со std_logic, где есть короткое замыкание и отсутствие управляющего воздействия.

V>Я таких сравнений перед каждым новым проектом делаю дофига, если не больше, но далекоидущих выводов не делаю из того факта, что в свободном доступе нет решения, идеально мне подходящего. Где надо — допиливаем, где проще написать самим, чем допилить монтра — пишем своё. (напр, с 0-ля построил серверную библиотеку протокола IAX2 — а этот монстрик далеко не на один файлик, даже не на один десяток). Но ты там на блогах целое шоу из этой будничной ситуации устроил. В общем, много эмоций.


Это не я устроил. Это устроил руководитель товарищей, что писали на SystemC. Который не смог произвести анализ.

V>>>Где ты увидел вопрос про "плоское пространство имён"? Похоже, ты не отличаешь "область видимости" от "уровня доступа/видимости".

T>>Так объясни.
V>Я имел ввиду разграничение видимости типа private/public на всех уровнях, а не только на уровне модулей. Я не верю в реальные программы без побочных эффектов (в файл же писать как-то надо), т.е. вопрос инкапсуляции "опасных" данных и кода по-прежнему открыт.

IO Int не совместимо с Int. Отрисовка в DrawingArea gtk2hs выполняется в RenderM, где надо делать специальные действия по вызову IO действий.

Там, где ты требуешь public/private, работает система типов.

T>>Автоматы на алгебраических типах делаются естественней и безопасней, чем на ООП.

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

Главное, что сама логическая часть работает правильно. И если мне понадобится хранить состояние автомата и ходить по нему вперёд-назад, то я могу это сделать лёгким движением руки.

Вдогонку: автомат для RS232 ~30 строк. Обернуть его в IO монаду для общения с Control.Parallel.Chan — три-пять строк. Ошибки будут явно не обёртке, поэтому беспокоиться на этот счёт не надо.

T>>Я не перфекционист и перфекционистов сторонюсь. перфекционизм и перфекционисты мешают наслаждаться жизнью.

V>Все еще не понимаю твоего упрямства и несогласия насчет того, что мы рассматривали класс задач и возможности Хаскеля, а не контекст конкретной проблемы. Ты продолжаешь делать вид, что мы обсуждаем ту конкретную задачу. Скажу по большому секрету: в подавляющем большинстве случаев я вступаю в спор из желания выбить из собеседника интересующую информацию. Но из тебя, похоже, ни по доброй воле, ни в провокациях не выбъешь, поэтому я и покинул ЭТОТ спор.

Тогда я не понимаю, чего ты его возобновил.

T>>У тебя, видимо, ещё не было опыта, когда ты неправильно что-то предполагал. Ты, видимо, никогда не ошибался в своих предположениях.

T>>Ну, так поздравляю: ты не так давно что-то предположил и ошибся! Это новый, очень ценный опыт.
V>Да, именно, через десяток постов узнать, что операция * не перегружаема в Хаскеле — это крайне ценно. Остальным, к сожалению, можно подтереться.

И это твоё новое знание тоже неверно: операция * перегружается.

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

V>>>Так это я неправильно мыслю об оптимизации вообще, или оно тебе в этом конкретном месте не очень надо было? У тебя с логикой вообще как?
T>>Опыт gcc показывает, что ты неправильно мыслишь об оптимизации вообще. Это понятно?
T>>Да и в этом конкретном случае тоже неправильно мыслишь. Поскольку лично мне это не было нужно.

V>gcc сливает MS VC++ в плане оптимизации, это понятно?


Я работал с товарищами из Optimitech.com, пользовался их библиотекой оптимизаций. Их сложение тоже было двухместным.

V>Бестолковые отсылки на "чужой опыт" без малейшего упоминания каких-либо предметных вещей — это бестолковая манера сама по-себе, это понятно?


Так прекрати со мной общаться.

V>Что мне понятно, так это то, что от реализации оптимизации в gcc ты крайне далек, и в лучшем случае слышал краем уха, как можно судить по твоим наивным "заглядываниям вглубь еще на 1 уровень" на основе матчинга.


Смотрим на gcc 4.4.4, что случайно оказался у меня под рукой. Файл tree-ssa-copy.c:
bool
may_propagate_copy (tree dest, tree orig)
  /* For memory partitions, copies are OK as long as the memory symbol
     belongs to the partition.  */
  if (TREE_CODE (dest) == SSA_NAME
      && TREE_CODE (SSA_NAME_VAR (dest)) == MEMORY_PARTITION_TAG)
    return (TREE_CODE (orig) == SSA_NAME
            && !is_gimple_reg (orig)
        && (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
            || bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (dest)),
                             DECL_UID (SSA_NAME_VAR (orig)))));


Что можно переписать на "заглядывании внутрь на основе матчинга" вот так:
may_propagate_copy dest@(SSA_NAME destNameVar) orig@(SSA_NAME (MEMORY_PARTITION origUID))
    = not (isGimpleReg orig)
      && (destNameVar == origNameVar
          || bitmap_bit_p (mptSymbols destNameVar) origUID)


Плюс-минус, тем не менее.

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


Лично я бы предпочёл вопрос в более прямой форме, например: "а вот если нам надо рассматривать ещё и вот такой вариант, что надо сделать?"

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

V>А твое рефлексирование и постоянное проявление недовольства фактом замеченной недоделанности (с переходом на личности) по-сути убило все обсуждение, это понятно?


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

Да, это убило дискуссию.

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

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


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

T>>>>Типобезопасность в ленивых ФЯ достигается проще всех остальных. Все остальные системы сложнее. BitC, например — авторы сами признают, что задача у них очень мощная и почти неподъёмная.

V>>>Наверно ты хотел сказать — вывод типов в ленивых ФЯ достигается проще всех остальных. Однако, ты же можешь и явно типы специфицировать, начиная от примитивных, типа int (или как они там в Хаскель называются). И тогда ленивость/нелинивость будут до фени.
T>>Я сказал ровно то, что я хотел сказать. Это не то, что ты считаешь, что я, наверное, сказал.
V>Я предположил, что ты неверно выразил верную мысль. Ибо твоя исходная формулировка некорректна (курить "строгую типизацию").

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

Поэтому не только вывод, но и проверка типов для ленивых ФЯ получается проще, чем у других ЯП.

T>>Похоже, ты вообще не утруждаешь себя размышлениями. Что будет означать (just nothing list) в сравнении с образцом? nothing — это конструктор, или переменная? Над Хаскелем изначально работали люди, которых приглашают специально поработать над C# или Java, чтобы решить очередные проблемы. Приглашают потому, что они overqualified для работы на полную ставку.

V>Угу, только сам автор Хаскеля выдвинул несколько иную версию произошедшего.

Какую же?
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Re[30]: Каким отладчиком пользовались разработчики Kx System
От: vdimas Россия  
Дата: 03.07.09 08:22
Оценка:
Здравствуйте, thesz, Вы писали:

T>Стоило с тобой согласиться, так ты с темой хрен знает какой давности вылез. Удивительно.


Да у меня rsdn@home на разных локациях валяется, и из одной из них неосторожно синхронизировался, забыв про давний неотправленный пост. Так что сорри, и спасибо за ответ.


T>Перегрузи в C++ оператор ';', чтобы она протягивала контекст, как в параметризованных монадах.

T>С перегруженной ';' мы можем считать сложность алгоритма без изменения исходного кода.

Насколько я понял, в Хаскеле не очень любят явное употребление ';', или позиционная запись тоже будет работать для этого случая?
В С++ можно перегрузить оператор ','.

T>Это нормальная логика. Если нужна оптимизация или контроль времени, я буду делать оптимизацию или контроль времени. Если мне говорят, что энергичные вычисления лучше всегда, я говорю "преждевременная оптимизация".


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

V>>Я потому и попросил тебя привести пример, ибо мой личный опыт мне не подсказал пока killer-example для этой фичи.

T>Для какой фичи? Определения времени выполнения? Так рилтайм приложения из района встраиваемых систем. Там, где можно использовать Atom.

Понятно, т.е. когда мы можем гарантировать, что процессорное время целиком отведено под нашу задачу. Для многозадачных операционок общего пользования это малость мимо. Возвращаясь к ';' и прочему, мне все-равно плохо понятно, как ты собрался считать время выполнения. Ты можешь подсчитать кол-во выражений, но как ты подсчитаешь их сложность, и тем паче время работы в тиках целевого проца?

T>Смотри на приблизительный сценарий нашей беседы:

T>T: Вот такая задача, вот так в ней мне помог компилятор...
T>V: А вот с этим он не помог.
T>T: С чем не помог?
T>V: А вот с этим — когда я делал похожее, у меня было вот эдак, и в твоём случае компилятор с этим не помог.
T>T: Но в моей задаче не было этого!
T>V: А почему тебе компилятор не помог с этим справиться?
T>T: Да потому, что в моей задаче это не было критично и я такого не делал!
T>V: То, что ты говоришь "не критично", означает слив.

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

T>Это глупо — требовать от меня, чтобы при решении моей частной задачи компилятор помог мне решить твою частную задачу.


Серьёзно?
Если я определяюсь — использовать этот ЯП или нет, но не так уж глупо. Насчет того человека с Явой и меня — в чем-то ты прав. Решение-то не простое: на одной чаше весов легкость написания своих велосипедов, на другой — мощь фреймворков и тонн библиотек (по крайней мере в интересующей меня области). А так же легкость в интероперабельности с различными COMпонентами и т.д. А то задачи-то разные: там веб-морду нарисовать, там пару окон ГУИ, здесь с кассовым аппаратом связаться и т.д., и каждая задача на .Net (иногда плюс С++) делается за считанные часы (если не минуты), а на Хаскеле подобные задачи требуют лишних приседаний. Я много просмотрел и твоих блогов и блогов твоих регулярных товарищей в ЖЖ, и те случаи, что пока видел, помогают лишь в самых примитивных случаях, а остальное делается гораздо сложнее даже, чем в С++, напр. типы, обобщаемые по интегральному параметру (зависимые).

Было бы всё так просто, не было бы этого и подобных разговоров.

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

T>Классы типов?

Не совсем, ты же не можешь использовать это при одном уровне ветвления матчинга, надо делать еще один уровень, и это вырождается в похожие уровни вложенностей if/else.

V>>И когда я уже десять раз, наверно, повторял о невозможности компилятора проверять "высокоуровневую логику", ты просто не понимаешь, очевидно, о чём тут идёт речь. А речь тут о том, что пока не придумали того самого "идеального языка", позволяющего задавать произвольные контракты. Была бы возможность задать контракт на такую структуру из нод с константами — и не пропустил бы компилятор твой недописанный матч.


T>Coq и иже с ними?


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

V>>Во-первых, большинство mainstream языков строго типизированные.

T>Не с достаточной степенью строгости.

Для С++ я уже говорил: избавь его от приведения в стиле С и от всяких xxx_cast<>, и это будет другой язык с другой репутацией. Во всем остальном он достаточно строг, а xxx_cast<> вылавливаются в проекте простым поиском. Мне известна система на миллионны строк без единого xxx_cast<>.

V>>Во вторых, конструирование DSL как раз и связано с обсуждаемой проблемой, в саму грамматику DSL и в "компилятор" закладываются ограничения — набор допустимых конструкций, что суть тоже контракт определённого вида. Если рассматривать DSL не для описания данных, а для целей программирования, то большинство из них — это "обрезанные" разновидности существующих ЯП, и в этой "обрезанности" и состоит смысл порождения языка (тебе, как стороннику DSEL персонально), дабы ограничить возможности базового языка до определённого набора безопасных в контексте задачи конструкций. До определённой степени это можно делать на системе типов, но лишь на определённом множестве требований.


T>Со временем всё более и более широком.


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


T>Описание команд модели процессора с учётом размеров регистров.

T>
T>        ...
T>


Или я ничего не понял, или здесь просто строгая типизация на обобщенных типах.


T>Смотри (применение NPlus смотри выше в BinOp):

T>
...
T>


T>>>А я по мелочи — размеры битовых векторов проверяю.

V>>И больше нигде как в ФП это невозможно...

T>Настолько просто — нет.


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

T>Что такое "некопируемый экземпляр"?


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

V>>А если это возможно в ФП через пару приседаний (те же монады), то зачем нам такое ФП?

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

T>Увы, и ах, но нет.


T>Допустим, что ты собрался писать модель процессора, которая запоминает изменения и позволяет ходить вперёд и назад по ходу выполнения программы.

T>В этом случае "мутабельная переменная" здесь не совсем подходит.

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


T>Буквально одна, конкретно State. А есть ещё Cont, List, Error... А есть ещё их комбинации...


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


T>Всё равно у меня на выходе функция, а её проще проверять.


T>Монада состояния это функция state -> (a,state). На любую часть монадического кода я могу подать какое угодно state и проверить, что же за a и что же за state он мне вернёт.

T>Вырезал, и проверил.
T>Очень просто.

А юнит-тестирование объектов в ООП разве не оно же?


V>>Признаюсь, грамотный ответ именно на этот вопрос интересует больше, чем все другие вместе взятые по теме ФП (ввиду практичности этого момента, в отличии от прочей задвигаемой здесь белеберды о "самоконтроллируемости всего").


T>Они связаны друг с другом.

T>При введении изменяемости в непротиворечивую систему типов надо снова доказывать её непротиворечивость.

Для С++ этим занимается целый коммитет, и эта вещь одноразова, вообще-то на весь язык, т.е., каждый разработчик компилятора уже не должен заниматься никакими док-вами.

V>>Суть понятна, без GC некоторые вещи выглядят страшно. Но прикол в том, что на том же C# практически 1-в-1 сделать можно было.

T>Не поверю, пока не увижу. Даже странно, что ты не написал те самые 20 строк кода, если всё настолько один-в-один.

1-в-1 по логике, не по размеру кода, ессно (описание типов малость говорливо в том же C#, согласен)... просто там миниатюрная логика у тебя, но сама подобная логика (создали экземпляр типа, отдали и забыли) достижима только в системах с GC.

V>>И еще лишь очередное подтверждение банальности, что частный случай проще общего в решении. Т.е., вы сравнивали монстра с 1% процентом его возможностей, а это неспортивно.


T>Для Хаскеля на тот момент существовал Hawk, на котором делали много интересных моделей разных устройств. Он, правда, до конца не собирался, но его исходники были доступны.

T>По изучению его ядро оказалось возможным упростить вот до того, что наверху по ссылке.

T>Товарищи, использовавшие SystemC, не смогли провести такой анализ.


Даже если смогли бы/хотели бы провести анализ, не упростили по фундаментальным причинам. Да, в С/С++ структура программы и способ решения задач почти всегда пляшет от доступной модели управления памятью, отсюда столько ручных "мета-описаний" в любых задачах обобщения алгоритмов на заведомо неизвестные структуры.

V>>Я имел ввиду разграничение видимости типа private/public на всех уровнях, а не только на уровне модулей. Я не верю в реальные программы без побочных эффектов (в файл же писать как-то надо), т.е. вопрос инкапсуляции "опасных" данных и кода по-прежнему открыт.


T>IO Int не совместимо с Int. Отрисовка в DrawingArea gtk2hs выполняется в RenderM, где надо делать специальные действия по вызову IO действий.


T>Там, где ты требуешь public/private, работает система типов.


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

Лично мне кажется, что public/private ортогональны системе типов, это лишь ср-во повышения безопасности кода при разделении труда, а от разделения труда в больших проектах никуда не деться.

V>>gcc сливает MS VC++ в плане оптимизации, это понятно?


T>Я работал с товарищами из Optimitech.com, пользовался их библиотекой оптимизаций. Их сложение тоже было двухместным.


V>>Бестолковые отсылки на "чужой опыт" без малейшего упоминания каких-либо предметных вещей — это бестолковая манера сама по-себе, это понятно?


T>Так прекрати со мной общаться.
Re[15]: Каким отладчиком пользовались разработчики Kx System
От: blackhearted Украина  
Дата: 03.07.09 09:29
Оценка:
Здравствуйте, Didro, Вы писали:

D>Ни и дальше уже цитата не Дейкстры, но о его трудах:

D>

D>По мнению Дейкстры, господствующий в компьютерной индустрии подход к программированию как к процессу достижения результата методом проб и ошибок («написать код — протестировать — найти ошибки — исправить — протестировать — …») порочен, поскольку стимулирует программистов не думать над задачей, а писать код, при этом совершенно не гарантирует корректность программ, которая не может быть доказана тестированием в принципе.
D>wiki


А чем может быть доказана корректность программ? Крутостью разработчика?
Re[31]: Каким отладчиком пользовались разработчики Kx System
От: thesz Россия http://thesz.livejournal.com
Дата: 03.07.09 09:51
Оценка:
T>>Перегрузи в C++ оператор ';', чтобы она протягивала контекст, как в параметризованных монадах.
T>>С перегруженной ';' мы можем считать сложность алгоритма без изменения исходного кода.
V>Насколько я понял, в Хаскеле не очень любят явное употребление ';', или позиционная запись тоже будет работать для этого случая?

';' использована мной вместо >>=. >>= исполняет роль точки с запятой в монадах

V>В С++ можно перегрузить оператор ','.


Ура!

V>>>Я потому и попросил тебя привести пример, ибо мой личный опыт мне не подсказал пока killer-example для этой фичи.

T>>Для какой фичи? Определения времени выполнения? Так рилтайм приложения из района встраиваемых систем. Там, где можно использовать Atom.
V>Понятно, т.е. когда мы можем гарантировать, что процессорное время целиком отведено под нашу задачу. Для многозадачных операционок общего пользования это малость мимо. Возвращаясь к ';' и прочему, мне все-равно плохо понятно, как ты собрался считать время выполнения. Ты можешь подсчитать кол-во выражений, но как ты подсчитаешь их сложность, и тем паче время работы в тиках целевого проца?

К любым операциям я могу пристегнуть типы со временем выполнения.

Вместо обычного Integer в + у меня будет MyInt cpu cycles, операция сложения для которого будет вычислять количество тиков для обеих подвыражений с учётом CPU.

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

Мне придётся подумать, но это возможно. Люди это делают.

T>>Это глупо — требовать от меня, чтобы при решении моей частной задачи компилятор помог мне решить твою частную задачу.

V>Серьёзно?
V>Если я определяюсь — использовать этот ЯП или нет, но не так уж глупо. Насчет того человека с Явой и меня — в чем-то ты прав. Решение-то не простое: на одной чаше весов легкость написания своих велосипедов, на другой — мощь фреймворков и тонн библиотек (по крайней мере в интересующей меня области). А так же легкость в интероперабельности с различными COMпонентами и т.д. А то задачи-то разные: там веб-морду нарисовать, там пару окон ГУИ, здесь с кассовым аппаратом связаться и т.д., и каждая задача на .Net (иногда плюс С++) делается за считанные часы (если не минуты), а на Хаскеле подобные задачи требуют лишних приседаний. Я много просмотрел и твоих блогов и блогов твоих регулярных товарищей в ЖЖ, и те случаи, что пока видел, помогают лишь в самых примитивных случаях, а остальное делается гораздо сложнее даже, чем в С++, напр. типы, обобщаемые по интегральному параметру (зависимые).

Зато часть с GUI будет работать с учётом части с Web лицом и с учётом части, работающей с COM-портом. И все будут работать с базой и если в базе что-то поменялось, то придётся протащить изменения везде, где надо.

V>Было бы всё так просто, не было бы этого и подобных разговоров.


Это проще, чем ты думаешь.

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

T>>Классы типов?
V>Не совсем, ты же не можешь использовать это при одном уровне ветвления матчинга, надо делать еще один уровень, и это вырождается в похожие уровни вложенностей if/else.

Покажи, я не понимаю.

V>>>И когда я уже десять раз, наверно, повторял о невозможности компилятора проверять "высокоуровневую логику", ты просто не понимаешь, очевидно, о чём тут идёт речь. А речь тут о том, что пока не придумали того самого "идеального языка", позволяющего задавать произвольные контракты. Была бы возможность задать контракт на такую структуру из нод с константами — и не пропустил бы компилятор твой недописанный матч.

T>>Coq и иже с ними?
V>Близко, но язык на сегодня непрактичен из-за узкой специализации и связанной с этим отсутствием нужной мне инфраструктуры для моих повседневных задач.

Лично моё мнение таково: прикладные части задачи решаются очень быстро, вне зависимости от ЯП. Главное — это ядро логики. Основной риск всегда там.

Именно поэтому Хаскель и именно поэтому движение в сторону зависимых типов.

Поэтому пиши ядро на самом контролирующем ЯП, всё остальное не представляет из себя нерешаемой или нерешённой проблемы.

Coq умеет генерировать код на Камле или Хаскеле. Значит, его легко переделать под генерацию F#. Если тебе нужна инфраструктура, то это твой путь.

V>>>Во-первых, большинство mainstream языков строго типизированные.

T>>Не с достаточной степенью строгости.
V>Для С++ я уже говорил: избавь его от приведения в стиле С и от всяких xxx_cast<>, и это будет другой язык с другой репутацией. Во всем остальном он достаточно строг, а xxx_cast<> вылавливаются в проекте простым поиском. Мне известна система на миллионны строк без единого xxx_cast<>.

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

T>>Со временем всё более и более широком.

V>Если говорить конкретно по Хаскель, то я дважды здесь задавал вопрос: что мешает человеку, использующему DSEL, вместо формирования требований к DSL (буде такая потребность) "сорваться" на прямое использование потенционально небезопасной всей мощи языка. По-сути, вопрос стоит в плоскости целей разработки DSL как таковых.

Типы.

T>>Описание команд модели процессора с учётом размеров регистров.

T>>
T>>        ...
T>>

V>Или я ничего не понял, или здесь просто строгая типизация на обобщенных типах.

Это строгая типизация с учётом смысла операций. Ты зря урезал NPlus, который стоит в операции Concat. На Java/C# это сделать нельзя вообще, на C++ очень сложно.

T>>>>А я по мелочи — размеры битовых векторов проверяю.

V>>>И больше нигде как в ФП это невозможно...
T>>Настолько просто — нет.
V>Явная специализация обобщенных типов конечно руль (это выход на метапрограммирование), но она опять же, не только в Хаскеле. Неужели простота только в кол-ве букв?

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

T>>Что такое "некопируемый экземпляр"?

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

T>>Серьёзно. Ну вот откуда ты знаешь, что на ЯП получится хуже, чем на ООЯП? Ты делал сравнительные реализации?
V>Как я сделаю тебе сравнительную реализацию, если рано или поздно нам приходится упираться в понятие "некопируемого экземпляра"?

Что такое "некопируемый экземпляр"?


Это всё требует более развёрнутого пояснения.

V>>>А если это возможно в ФП через пару приседаний (те же монады), то зачем нам такое ФП?

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

T>>Увы, и ах, но нет.


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

T>>Буквально одна, конкретно State. А есть ещё Cont, List, Error... А есть ещё их комбинации...
V>>>Ну и для чего тогда весь первоначальный цирк с "чистым" ФП, если на всех этих моделях мутабельных регистров можно так же точно смоделировать все грабли с побочными эффектами, как в императивных языках?
T>>Всё равно у меня на выходе функция, а её проще проверять.
T>>Монада состояния это функция state -> (a,state). На любую часть монадического кода я могу подать какое угодно state и проверить, что же за a и что же за state он мне вернёт.
T>>Вырезал, и проверил.
T>>Очень просто.

V>А юнит-тестирование объектов в ООП разве не оно же?


Отличается количество движений программиста.

Для тестирования определённого участка поведения объекта тебе надо подготовить состояние специальными действиями, тогда как на функцию ты можешь подать состояние непрямую.

Вообще, эта мысль про количество движений органов программиста очень хороша.

V>>>Признаюсь, грамотный ответ именно на этот вопрос интересует больше, чем все другие вместе взятые по теме ФП (ввиду практичности этого момента, в отличии от прочей задвигаемой здесь белеберды о "самоконтроллируемости всего").

T>>Они связаны друг с другом.
T>>При введении изменяемости в непротиворечивую систему типов надо снова доказывать её непротиворечивость.
V>Для С++ этим занимается целый коммитет, и эта вещь одноразова, вообще-то на весь язык, т.е., каждый разработчик компилятора уже не должен заниматься никакими док-вами.

Но для создания встроенных языков и/или библиотек тебе придётся доказывать это снова и снова. Для каждой библиотеки и для каждого сочетания библиотек.

V>>>Суть понятна, без GC некоторые вещи выглядят страшно. Но прикол в том, что на том же C# практически 1-в-1 сделать можно было.

T>>Не поверю, пока не увижу. Даже странно, что ты не написал те самые 20 строк кода, если всё настолько один-в-один.
V>1-в-1 по логике, не по размеру кода, ессно (описание типов малость говорливо в том же C#, согласен)... просто там миниатюрная логика у тебя, но сама подобная логика (создали экземпляр типа, отдали и забыли) достижима только в системах с GC.

Количество движений, помнишь? Количество движений. Логика никого не интересует.

T>>Товарищи, использовавшие SystemC, не смогли провести такой анализ.

V>Даже если смогли бы/хотели бы провести анализ, не упростили по фундаментальным причинам.

Да брось ты.

V>Да, в С/С++ структура программы и способ решения задач почти всегда пляшет от доступной модели управления памятью, отсюда столько ручных "мета-описаний" в любых задачах обобщения алгоритмов на заведомо неизвестные структуры.


Ты пытаешься их оправдать, исходя из своего опыта.

Моделирование (потактово точное) аппаратуры достаточно сильно отличается от обычного программирования. С точки зрения распределения памяти в более простую, а с точки зрения размышлений — в более сложную сторону.

T>>Там, где ты требуешь public/private, работает система типов.

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

Что сделает твой безответственный, либо начинающий программист в случае наличия public/private?

Да ровно то же самое.

V>Лично мне кажется, что public/private ортогональны системе типов, это лишь ср-во повышения безопасности кода при разделении труда, а от разделения труда в больших проектах никуда не деться.


Область видимости, действительно, достаточно независима от системы типов.

С типами, однако интересней: Parser не даёт возможность читать файлы. Если не сделать ему интерфейс MonadIO. А последнее будет видно.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Re[15]: Каким отладчиком пользовались разработчики Kx System
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.07.09 12:12
Оценка:
Здравствуйте, Didro, Вы писали:

D>Ни и дальше уже цитата не Дейкстры, но о его трудах:

D>

D>По мнению Дейкстры, господствующий в компьютерной индустрии подход к программированию как к процессу достижения результата методом проб и ошибок («написать код — протестировать — найти ошибки — исправить — протестировать — …») порочен, поскольку стимулирует программистов не думать над задачей, а писать код, при этом совершенно не гарантирует корректность программ, которая не может быть доказана тестированием в принципе.
D>wiki


Дейкстра говорит большую банальность, я формулирую такое по другому — писать код надо головой а не дебуггером(руками, ногами).
Re[17]: Каким отладчиком пользовались разработчики Kx System
От: heavyweapondude  
Дата: 20.07.09 10:30
Оценка:
Здравствуйте, FR, Вы писали:

...

Почти наверняка WinDbg + VMWare решат вопрос отладки
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.