Вот я беру Хаскель, пишу в нём `:k (->)` и вижу:
Prelude> :k (->)
(->) :: * -> * -> *
Но почему (->) имеет два параметра и результат (три `*`), а не один параметр и результат?
Я, видимо, не понимаю чего-то очень базового, но я «не понимаю чего именно я не понимаю» :(
Ну и второй (но скорее уже факультативный) вопрос: а зачем вообще делать функцию экземплярами классов Functor \ Applicative \ Monad?
Всегда нужно валидировать и валидировать много. Это постоянные if-ы, явные или не очень, при любом обращении к объекту. Сильно ломает уже оптимизации железные.
Вообще подчёркнутое предложение в общем случае не верно. В смысле оверхэд на if, конечно остаётся, но «железные оптимизации» в нормальном языке это не ломает. Т.к. если вы пишите в языке с требованиями к производительности, то у вас должен быть какой-то аналог assert или unlikely / never макросов, — выравнивающий поток управления (т.е. штатный код всегда должен делаться по провалам, т.е. без джампов).
Честно говоря довольно однобокий подход.
В сегодняшних условиях, когда производительность условного «core i3» более не растёт со сменой поколений просматривается аж несколько подходов к возможности и дальше писать всё более и более «привлекательный» для пользователя (т.е. красивый и функциональный) код.
При этом, конечно, каким будет конечное решение: какой-то «чистый» подход, смешанный подход либо решение придёт «со стороны» сегодня не понятно:
— многопоточное программирование — тот же серверный ARM в терафлопсах уже свою производительность меряет (да мерялка не идеальна). Проблем у этого подхода много: отсутствие устоявшихся и боле-менее универсальных подходов и инструментов, проблемы при написании «монолитных» приложений, плохое распараллеливание (зависимость по данным или real-time требования, или ещё что-то) для части приложений, возрастание простоев (lock-free и wait-free алгоритмы всё равно не бесплатны) с увеличением числа потоков, необходимость достаточно производительного потока для пользовательского интерфейса и т.д.
— специальные ускорители — тут мобильные устройства, в массовом сегменте, пионеры. Графика (даже 2Д)? Звук? Кодаки? Шифрование — пожалуйста воспользуйтесь спец. устройством и ни в чём себе не отказывайте.
ИМХО комбинирование этих двух подходов (для «прожорливых» задач выделенное устройство, всё остальное хорошо распараллелено) на приличное время компенсирует отсутствие роста производительности «условного core i3»
— переход с «условной Java[Script]» на «условный Rust» — ну поскольку прирёрло (или скоро припрёт) и мощности реально почти не растут, то придётся пересаживаться. Переход на С \ С++ выглядит нереальным.
— обучение массового программиста писать алгоритмически производительный код — да мне видится, что заявленный в статье метод решения проблемы «процессоры больше не становятся быстрее» стоит где-то здесь, после многопоточности, спец-вычислителей, перехода на rust…
Ну а совсем фантастичных сценариев, типа выполнения всего в облаках через G5 — выше уже накидали, но, по ряду причин, слабо верится ;)
Я бы (если бы позволила задача) наверное просто поместил бы фигуру в «user interface rectangle». И отдельно менял положение фигуры внутри этакого «интерфейс-контейнера» \ отдельно положение контейнера во фрейме — тогда перетаскивание маркеров вправо\влево вверх\вниз делалось бы вообще одной строкой.
Но после этого дисклеймера могу выступить адвокатом дьявола:
1. Насколько я помню (но не понимаю, только видел разъяснения) модели при замене i на -i не полностью эквивалентны. Может быть у ребят именно настолько чувствительная к математической обработке модель.
2. 10 строчек кода при перетаскивании левого (правого \ верхнего \ нижнего...) края могут появиться, если это действие определено (условно) как scale + сохранение геометрического центра — ну то есть тогда надо сначала раздвинуть размеры фигуры по оси, найти новое положение центра, переместить новое положение центра, пара комментариев, пара пустых строк… 10 наверное наберётся
// не спрашивайте меня — не знаю ей богу откуда берётся одновременно 10 строк кода для перемещения левого края и отдельная функция для каждого действия.
Да и вообще «вложения в экономику» (просто индекс ММВБ) за 12 лет выросли примерно на 60% в рублях, это 4% годовых.
Ну то есть вы подгоняете условия под ответ и… с блеском демонстрируете нужную вам статистику…
Э… я точно на хабре (ресурсе известном высокой грамотностью своих пользователей) веду диалог, а не в какой-нибудь соц.сети?
Честно говоря раз уж пошли такие уловки — наверное эта ветка себя исчерпала.
В смысле калькуляции солидарная система очень близка к накопительной.
Я бы даже сказал к лучшим реализациям накопительной — при которой отчисления идут в акции (т.е. приобретается «кусочек экономики») а не в какие-нибудь облигации и т.п.
Значительную разницу я вижу только в том, что при солидарной действительно возникает желание «усреднить» пенсии — т.е. вместо того, чтобы платить соц.пособия бывшим тунеядцам платят полноценные пенсии за счёт работавших (естественно всё делается через математический оператор «отложенного платежа» хД)
да на то, что сверх налогооблагаемой базы платят 10%.
Т.е. я вас понял так:
1. до 100тыс/месяц обложение 23% (или сколько там). Но с этих денег хотя бы мне пенсию будут платить. В целом ± честно.
2. сверх 100тыс/месяц баллы не идут (проверял в пенсионном калькуляторе) и это чистая благотворительность (в пользу тех моих одноклассников, которые побухивали вместо уроков, когда я сидел и ботал математику с IT)
Про пункт 2 я просто не знал и просил подтверждающую ссылку.
И был несколько удивлён этим фактом, т.к. периодически поглядывал одним глазом за пенсионной реформой (хотя бы в формате «хватит ли пенсии на кусочек хлеба, если считать что 'всё будет ± как сейчас'»)/
ПС
Да лучше на такие мусорные сайты, которые мешают читать и вымогают почту ссылок не давать.
Вот по 2020 году сразу ищется ссылка
Проблема в том, что соц.сети являются естественными монополиями.
Действительно если 60% друзей и потребляемого условным Джоном контента в ФБ — он перейдёт на ФБ (*)
И пока соц.сети являются естественными монополиями — рассказы о «частной цензуре» в существенной степени фарисейство (т.е. формально в сферическом вакууме верны, но по сути издевательство).
*) Решается это крайне сложно (как пытаются в Династии) через открытый API взаимодействия между «хранением» и «отображением» информации. Но получается неповоротливый монстр из комитетов по работе с комитетом по работе со стандартом описания протокола…
Ну общаться на уровне SO это попроще чем книгу по незнакомой области читать (как минимум я надеюсь что «незнакомость» в этом случае не будет так сильно вылазить).
1. Смешение табов и пробелов куда хуже чем отдельно табы или пробелы.
2. Табы «в целом» скорее уходящая CodeStyle конвенция. Но например в Linux Kernel Code Style они родимые (не заменяются пробелами, да ещё и по 8 символов) — а оттуда зачастую попадают в CodeStyle контор занимающихся системным ПО.
ПС
Абсолютно с вами согласен, что увольнять! джуниара! вместо того чтобы объяснить! — это совсем какой-то моветон.
Джун на то и джун, чтобы учиться на работе, а не с ходу выдавать желаемый код.
На практике наверное действительно лучше «начинать с середины». Особенно в ситуации когда некому задать FAQ (воспользоваться чужой интуицией).
Просто мне вот всегда было комфортнее когда понимаешь на пару уровней абстракции вглубь что делается.
Вот скажем той же интуиции в «функциональном стиле программирования» у меня совсем нет (вернее есть неправильно работающая унаследованная от императивщины).
Скажем написал «решето эратосфена» в функциональном (в смысле «filter \ list» а не в смысле «без сайд эффектов») и с ходу ошибся в О-сложности работы.
>> Пишите код, показывайте его людям, получайте фидбек.
А куда показать-то свой (достаточно тупой чтобы было интересно другим людям) код. Так чтобы сходу не послали на…
Вот интересно что раньше-то никогда в такой ситуации не бывал…
Да вероятно я неверно понял β-редукцию (или читал про упрощённый пример исчисления).
Я её понял просто как раскрытие (уж не помню корневой или листовой) \-функции
>> любая функция принимает ровно 1 аргумент,
Вещь теоретически крайне красивая.
Но.
В \- исчислении (тех местах, что я видел, я конечно тот ещё специалист) пишут же:
\ xyz.M(...) — т.е. явно в сигнатуре (до точке) указывают 3 аргумента.
Спасибо вам за ваш блог, отчасти он подвигнул меня начать учить FP (в частности остановился на Haskell, хотя есть вещи немного смущающие).
>> ИМХО лучше с практики начинать.
Ну в метро-то надо что-то делать. Тем более в теории я не глубоко (всего лишь главы про \-исчисление и комбинаторы книги «14 занимательных эссе о хаскел»).
Просто удивляет что не очень понимаю что там написано (собственно подозреваю что там пара базовых моментов недообъяснена для совсем новичка).
Можно я не в подходящей для этого теме вас немного помучаю:
1. Оптимизации в движке Haskell:
— они в основном на AST делаются (или в IR)?
— все далаются в compile-time или сам бинарник (exe\elf) занимается оптимизацией и (JIT\интерпретацией) — где-то видел такую версию, но неправдоподобно по скорости.
2. Зачем нужно каррирование? Как отдельная и важная парадигма отличительная черта парадигмы FP?
Пока вижу лишь «сахар» для «абстрактных фабрик» или виде затыкания дыр там где по синтаксису нужна функция 1й переменной, типа:
map ( (\x y -> x /= y) param_var) param_list
Который (сахар / поддержка паттернов) на отдельное важное свойство парадигмы не тянет
3. Что лучше из (относительно теоретического) почитать для улучшения скила в FP (важное дополнение — на русском).
Наверное тут тоже два вопроса:
— в какую сторону (теория типов \ CT \ частично рекурсивные функции \ ещё что-то)?
— на какой именно книге стоит остановиться?
1. Преждевременные оптимизации — зло.
Узнай место, которое замедляет программу, реализуй его на C(*).
Собственно про профилирование кода сказали, а дальше свернули куда-то не туда и стали говорить про всякие микрооптимизации, зачем?
*) по аналогии — мало кто пишет весь код сейчас на assembler, если узкое место CPU находят самую прожорливую ф-ию и переписывают её и только её (например используя параллельность по данным через SSE инструкции)
2. Не упоминуть про CPython (и другие интерпретаторы байткода), почему?
3. На фоне 1,2 то что описано в статье даст весьма незначительные улучшения.
3.1 Вот это чрезмерная оптимизация, даже в сравнении с остальными пунктами статьи.
>> Как это возможно? Дело в том, что при обработке большого набора данных без использования генераторов (итераторов) данные могут привести к переполнению L1-кэша процессора, что значительно замедлит операции по поиску значений в памяти.
Даже на фоне присутствующих в статье советов это уж совсем экономия на спичках.
Интерпретатор всё равно загрузится в L1-instraction-cache (который свой для кода\данных).
А уж пара промахов по data-cache дадут доли процентов на фоне общей неспешности внутренних мехазинмов python, типа __getattribute__ (которые вовсе не для производительности так проектировались).
>> Перспективы не радужные, все мужское население, которое остается без работы идет в строительство или перевозки.
Понял да, удачи вам.
Вот я сейчас в (чем-то) похожей ситуации.
Решил учить FP (решил ознакомиться с базисом — лямбда и комбинаторным исчислениями) и чувствую себя таким тупым, как те «троечники» которые в студенчестве вечно какие-то очевидные вещи не понимали.
И вот думаю то-ли я действительно тупее стал, то-ли требуется «период въезжания» в практически полностью новую тему.
>> до них сложно доходит понятие профессионализм и почему надо платить больше, чем бригаде забулдыг.
Ну я, конечно, в Мск а не провинции.
Но по моим понятиям профессионалы берут столько же сколько и забулдыги. Просто профессионалы (с хорошо налаженным конвейром работы и инструментом) делают работу за 1 день, а забулдыги за 3.
Вот я беру Хаскель, пишу в нём `:k (->)` и вижу:
Prelude> :k (->)
(->) :: * -> * -> *
Но почему (->) имеет два параметра и результат (три `*`), а не один параметр и результат?
Я, видимо, не понимаю чего-то очень базового, но я «не понимаю чего именно я не понимаю» :(
Ну и второй (но скорее уже факультативный) вопрос: а зачем вообще делать функцию экземплярами классов Functor \ Applicative \ Monad?
Вот это как раз является весомой причиной заинтересоваться вами куда подробнее.
Оспаривал-то утверждение "(помимо неопределённого размера) if внутри runtime-типизации ломает аппаратные оптимизации".
Нет не ломает (есть средства чтобы не ломались) хД
Вообще подчёркнутое предложение в общем случае не верно. В смысле оверхэд на if, конечно остаётся, но «железные оптимизации» в нормальном языке это не ломает. Т.к. если вы пишите в языке с требованиями к производительности, то у вас должен быть какой-то аналог assert или unlikely / never макросов, — выравнивающий поток управления (т.е. штатный код всегда должен делаться по провалам, т.е. без джампов).
В сегодняшних условиях, когда производительность условного «core i3» более не растёт со сменой поколений просматривается аж несколько подходов к возможности и дальше писать всё более и более «привлекательный» для пользователя (т.е. красивый и функциональный) код.
При этом, конечно, каким будет конечное решение: какой-то «чистый» подход, смешанный подход либо решение придёт «со стороны» сегодня не понятно:
— многопоточное программирование — тот же серверный ARM в терафлопсах уже свою производительность меряет (да мерялка не идеальна). Проблем у этого подхода много: отсутствие устоявшихся и боле-менее универсальных подходов и инструментов, проблемы при написании «монолитных» приложений, плохое распараллеливание (зависимость по данным или real-time требования, или ещё что-то) для части приложений, возрастание простоев (lock-free и wait-free алгоритмы всё равно не бесплатны) с увеличением числа потоков, необходимость достаточно производительного потока для пользовательского интерфейса и т.д.
— специальные ускорители — тут мобильные устройства, в массовом сегменте, пионеры. Графика (даже 2Д)? Звук? Кодаки? Шифрование — пожалуйста воспользуйтесь спец. устройством и ни в чём себе не отказывайте.
ИМХО комбинирование этих двух подходов (для «прожорливых» задач выделенное устройство, всё остальное хорошо распараллелено) на приличное время компенсирует отсутствие роста производительности «условного core i3»
— переход с «условной Java[Script]» на «условный Rust» — ну поскольку прирёрло (или скоро припрёт) и мощности реально почти не растут, то придётся пересаживаться. Переход на С \ С++ выглядит нереальным.
— обучение массового программиста писать алгоритмически производительный код — да мне видится, что заявленный в статье метод решения проблемы «процессоры больше не становятся быстрее» стоит где-то здесь, после многопоточности, спец-вычислителей, перехода на rust…
Ну а совсем фантастичных сценариев, типа выполнения всего в облаках через G5 — выше уже накидали, но, по ряду причин, слабо верится ;)
Но после этого дисклеймера могу выступить адвокатом дьявола:
1. Насколько я помню (но не понимаю, только видел разъяснения) модели при замене i на -i не полностью эквивалентны. Может быть у ребят именно настолько чувствительная к математической обработке модель.
2. 10 строчек кода при перетаскивании левого (правого \ верхнего \ нижнего...) края могут появиться, если это действие определено (условно) как scale + сохранение геометрического центра — ну то есть тогда надо сначала раздвинуть размеры фигуры по оси, найти новое положение центра, переместить новое положение центра, пара комментариев, пара пустых строк… 10 наверное наберётся
// не спрашивайте меня — не знаю ей богу откуда берётся одновременно 10 строк кода для перемещения левого края и отдельная функция для каждого действия.
Ну то есть вы подгоняете условия под ответ и… с блеском демонстрируете нужную вам статистику…
Э… я точно на хабре (ресурсе известном высокой грамотностью своих пользователей) веду диалог, а не в какой-нибудь соц.сети?
Честно говоря раз уж пошли такие уловки — наверное эта ветка себя исчерпала.
Я бы даже сказал к лучшим реализациям накопительной — при которой отчисления идут в акции (т.е. приобретается «кусочек экономики») а не в какие-нибудь облигации и т.п.
Значительную разницу я вижу только в том, что при солидарной действительно возникает желание «усреднить» пенсии — т.е. вместо того, чтобы платить соц.пособия бывшим тунеядцам платят полноценные пенсии за счёт работавших (естественно всё делается через математический оператор «отложенного платежа» хД)
Т.е. я вас понял так:
1. до 100тыс/месяц обложение 23% (или сколько там). Но с этих денег хотя бы мне пенсию будут платить. В целом ± честно.
2. сверх 100тыс/месяц баллы не идут (проверял в пенсионном калькуляторе) и это чистая благотворительность (в пользу тех моих одноклассников, которые побухивали вместо уроков, когда я сидел и ботал математику с IT)
Про пункт 2 я просто не знал и просил подтверждающую ссылку.
И был несколько удивлён этим фактом, т.к. периодически поглядывал одним глазом за пенсионной реформой (хотя бы в формате «хватит ли пенсии на кусочек хлеба, если считать что 'всё будет ± как сейчас'»)/
ПС
Да лучше на такие мусорные сайты, которые мешают читать и вымогают почту ссылок не давать.
Вот по 2020 году сразу ищется ссылка
Действительно если 60% друзей и потребляемого условным Джоном контента в ФБ — он перейдёт на ФБ (*)
И пока соц.сети являются естественными монополиями — рассказы о «частной цензуре» в существенной степени фарисейство (т.е. формально в сферическом вакууме верны, но по сути издевательство).
*) Решается это крайне сложно (как пытаются в Династии) через открытый API взаимодействия между «хранением» и «отображением» информации. Но получается неповоротливый монстр из комитетов по работе с комитетом по работе со стандартом описания протокола…
Ну общаться на уровне SO это попроще чем книгу по незнакомой области читать (как минимум я надеюсь что «незнакомость» в этом случае не будет так сильно вылазить).
2. Табы «в целом» скорее уходящая CodeStyle конвенция. Но например в Linux Kernel Code Style они родимые (не заменяются пробелами, да ещё и по 8 символов) — а оттуда зачастую попадают в CodeStyle контор занимающихся системным ПО.
ПС
Абсолютно с вами согласен, что увольнять! джуниара! вместо того чтобы объяснить! — это совсем какой-то моветон.
Джун на то и джун, чтобы учиться на работе, а не с ходу выдавать желаемый код.
На практике наверное действительно лучше «начинать с середины». Особенно в ситуации когда некому задать FAQ (воспользоваться чужой интуицией).
Просто мне вот всегда было комфортнее когда понимаешь на пару уровней абстракции вглубь что делается.
Вот скажем той же интуиции в «функциональном стиле программирования» у меня совсем нет (вернее есть неправильно работающая унаследованная от императивщины).
Скажем написал «решето эратосфена» в функциональном (в смысле «filter \ list» а не в смысле «без сайд эффектов») и с ходу ошибся в О-сложности работы.
>> Пишите код, показывайте его людям, получайте фидбек.
А куда показать-то свой (достаточно тупой чтобы было интересно другим людям) код. Так чтобы сходу не послали на…
Вот интересно что раньше-то никогда в такой ситуации не бывал…
Серьёзно?
Ссылкой поделитесь?
Да вероятно я неверно понял β-редукцию (или читал про упрощённый пример исчисления).
Я её понял просто как раскрытие (уж не помню корневой или листовой) \-функции
Вещь теоретически крайне красивая.
Но.
В \- исчислении (тех местах, что я видел, я конечно тот ещё специалист) пишут же:
\ xyz.M(...) — т.е. явно в сигнатуре (до точке) указывают 3 аргумента.
>> ИМХО лучше с практики начинать.
Ну в метро-то надо что-то делать. Тем более в теории я не глубоко (всего лишь главы про \-исчисление и комбинаторы книги «14 занимательных эссе о хаскел»).
Просто удивляет что не очень понимаю что там написано (собственно подозреваю что там пара базовых моментов недообъяснена для совсем новичка).
Можно я не в подходящей для этого теме вас немного помучаю:
1. Оптимизации в движке Haskell:
— они в основном на AST делаются (или в IR)?
— все далаются в compile-time или сам бинарник (exe\elf) занимается оптимизацией и (JIT\интерпретацией) — где-то видел такую версию, но неправдоподобно по скорости.
2. Зачем нужно каррирование? Как отдельная и важная
парадигмаотличительная черта парадигмы FP?Пока вижу лишь «сахар» для «абстрактных фабрик» или виде затыкания дыр там где по синтаксису нужна функция 1й переменной, типа:
map ( (\x y -> x /= y) param_var) param_list
Который (сахар / поддержка паттернов) на отдельное важное свойство парадигмы не тянет
3. Что лучше из (относительно теоретического) почитать для улучшения скила в FP (важное дополнение — на русском).
Наверное тут тоже два вопроса:
— в какую сторону (теория типов \ CT \ частично рекурсивные функции \ ещё что-то)?
— на какой именно книге стоит остановиться?
Узнай место, которое замедляет программу, реализуй его на C(*).
Собственно про профилирование кода сказали, а дальше свернули куда-то не туда и стали говорить про всякие микрооптимизации, зачем?
*) по аналогии — мало кто пишет весь код сейчас на assembler, если узкое место CPU находят самую прожорливую ф-ию и переписывают её и только её (например используя параллельность по данным через SSE инструкции)
2. Не упоминуть про CPython (и другие интерпретаторы байткода), почему?
3. На фоне 1,2 то что описано в статье даст весьма незначительные улучшения.
3.1 Вот это чрезмерная оптимизация, даже в сравнении с остальными пунктами статьи.
>> Как это возможно? Дело в том, что при обработке большого набора данных без использования генераторов (итераторов) данные могут привести к переполнению L1-кэша процессора, что значительно замедлит операции по поиску значений в памяти.
Даже на фоне присутствующих в статье советов это уж совсем экономия на спичках.
Интерпретатор всё равно загрузится в L1-instraction-cache (который свой для кода\данных).
А уж пара промахов по data-cache дадут доли процентов на фоне общей неспешности внутренних мехазинмов python, типа __getattribute__ (которые вовсе не для производительности так проектировались).
Понял да, удачи вам.
Вот я сейчас в (чем-то) похожей ситуации.
Решил учить FP (решил ознакомиться с базисом — лямбда и комбинаторным исчислениями) и чувствую себя таким тупым, как те «троечники» которые в студенчестве вечно какие-то очевидные вещи не понимали.
И вот думаю то-ли я действительно тупее стал, то-ли требуется «период въезжания» в практически полностью новую тему.
>> до них сложно доходит понятие профессионализм и почему надо платить больше, чем бригаде забулдыг.
Ну я, конечно, в Мск а не провинции.
Но по моим понятиям профессионалы берут столько же сколько и забулдыги. Просто профессионалы (с хорошо налаженным конвейром работы и инструментом) делают работу за 1 день, а забулдыги за 3.