All streams
Search
Write a publication
Pull to refresh
4
0.3
Send message
Извините, я вас не очень понял.

Вообще примеры типа приведённого в статье «варения борща» ужасны для программирования.

Приведённый вами пример (для удалённого доступа) просто очень неудачен для FP, кмк (для Haskell в частности). Потому, как само по себе ФП очень тяжело ложиться на низкоуровневые вещи (хотя бы потому, что любое обращение к аппаратуре — IO, т.е. завёрнуто в свой слой монадок).

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

Всё это завёрнуто в Maybe. Тогда и «бойлерплейта» обслуживающего плохие случаи не будет.
>> Если бы вы сказали, «монады — это абстракция над вычислениями в контексте, независимая от вычислителя», а потом добавили, что мол «на практике сама абстракция не нужна…

Извините мне вот стало „легко и понятно“, когда я для себя понял что зачем монада — это просто такой способ разделить вычисления над значениями и `контекст` доставшийся от предыдущих вычислений.
При этом: „монада это просто такой способ“ — тут слово просто обманчиво, поскольку в него запихали много чего, позволяющие получать интуитивно понятный результат при цепочках вычислений, и использовать IO как `контекст`(и наверняка вы добавите много чего ещё в это „просто“).

Так вот вопрос: интуитивно-удобное для меня понимание довольно близко к тому, с чем вы могли бы поспорить. Есть какая-то конкретная проблема в этом (удобном для меня) понимании?
Не первый раз вижу попытки «просто объяснить ФП».
И место с монадами — во многих таких статьях описывается похоже и откровенно вводит в заблуждение (я читал похожее, когда ещё не знал ФП, меня обманули тогда и обманули бы вы сейчас).

Я бы хотел, чтобы 6 месяцев назад мне объяснили как-то так (если бы мог объяснить сам — написал бы статью):
1. Есть функциональная парадигма (с чистыми ф-иями и иммутабельными данными. Даст она вам то-то и то-то). В промышленных языках давно поддерживается её имитация (map, reduce, lampda....)
2. Сама по себе функциональная парадигма «вычислительно слабее». Для удобства, краткости кода (и для того, чтобы хоть частично компенсировать «отставание вычислительных возможностей» ФП) прямо-таки напрашиваются вот такие улучшения: ВФП, lambda, Curring. А также вот такие: Functor, Applicative, Monad.
3. Функтор, это просто контейнер (функтор уже контейнер, умеющий помещать в себя значения, да!)
Монада — это тоже контейнер. Зачем нам «ещё контейнер» — у монады можно реализовать достаточно сильную логику, отдельно для обработки элементов, а отдельно для контейнера.
Пример? Пожалуйста? Цепочка вычислений на Maybe (когда нам не нужен «бойлерплейт» код для плохих случаев). Хорошо переписывается с поддержкой логов в виде монады Writer.
>> Если будет интересно, скажите, я внизу добавлю список ресурсов, которые местные преподаватели активно используют для обучения. Некоторые из них очень неплохие.

Да пожалуйста добавьте.
Как раз хочу подтянуть английский до уровня выше, чем «читать мануалы по своему профилю».
Мне видится, что в таком случае наиболее востребованной частью математики будет «составление приближённых моделей».

Поскольку хоть вальфрам альфа и лучше получает решения сформулированных выражений (хотя иногда численно), но вот проконтролировать, что «решение уравнений» и «решение исходной задачи» это одно и то же должен именно человек.

И тут уже должен быть навык понять «туда ли мы идём вместе с компьютером».
>> Я бы послушал интервью с каким-нибудь политиканом. В идеале — с Яровой, Луговым и прочими клишасами.

Ну было же интервью Яровой Познеру. Посмотрите.

ПС
Хотя если резюмировать личные впечатления, то одно из самых слабых (я бы даже сказал провальное) интервью Познера. Как говорится «к такому его жизнь не готовила».
Ох как тяжело, с этими статьями на Хабре (хотел расширить кругозор, а теперь ничего не понимаю).

Вот пол-месяца назад я думал, что почти разобрался с Haskell.
Потом прочитал 4 «лонгрида», с обсуждениями call\cc и продолжениями и связей с монадами и перестал что-либо понимать (окончательно?).

Объясните пожалуйста если кто-то найдёт в себе силы и время.

Попробую по-порядку:
I. Вот моё представление о Haskell (до прочтения заумных комментариев на хабре):
0. Expressions (в смысле ссылочно-прозрачные функции) это хорошо при прочих равных.
Но:
1. «statement» часто обладает более насыщенной семантикой, чем «expressions» (сравните изменение элемента дерева в Haskell с императивом. А изменение 1го узла графа!?).
2. Чтобы FP-программы не оказались многословнее потребовались способы «более сильной» комбинации выражений, в сравнении с промышленными языками
3. Вот «из-за 1 и 2» и ввели такие понятия, как аппликативные функторы и монады (монады, также, оказались удобны для сокрытия внутри IO, почему так — надо разобраться (*)).

Это было очень удобно, хотя и оставались «мелкие» вопросы, с которыми оставалось разобраться:
I.a. Правда ли, что "<-" из do-нотации «невыразима без do-нотации сама по себе» (хотя любые законченные функции в do-нотации могут быть альтернативно выражены через комбинирование).
I.b В какой именно момент происходят вычисления монадических функций (как сами значения, так и эффекты)?
I.b.ii Для монады IO применяется общее правило про время вычисления функций (с учётом зависимости по данным через «переменную RealWorld») или нет?

Это примерно моё представление о Хаскель 2 недели назад оно «не бесповоротно неправильное»?
Можно же чуть-чуть доразобраться и идти дальше?

II.
Вот пришло время разобраться почему: «монады, а не аппликативные функторы?», «IO как монады, а не отдельный механизм», а также «I.a, I.b, I.b.ii»,
Прочитал 4 больших статьи на хабре с обсуждением и зарубами специалистов по ФП на 200+ комментариев, несколько статей со ссылками на новые понятия…

Итак я узнал (spoiler: и офигел понял что ничего не понял):
II.a do-нотация зачастую многословнее, чем комбинирование через >>=. Но писать надо всё равно через do (а не вырабатывать интуицию «функционального подхода» на >>=), — я думал ровно наоборот
II.b монады это «просто» реализация паттерна call/cc, — это вообще как? Ну т.е. что такое паттерн call/cc я прочитал (передаём функцию «досрочного» возврата в лямбду).
II.c монады реализуют ту же семантику, что и async\await, — тут я опять ничего не понял. Какое это имеет отношение, к ФП или Хаскелю (кроме исторически-дизайнерского legacy)? Чистые же функции с ленивыми вычислениями и так распараллелены по данным? Зачем нам мыслить категориями async\await?
II.d IO через монады это сознательный дизайн хаскеля, — но зачем!? Это же IO надо связать в последовательность, для этого надо между IO-вызовами передавать «скрытую переменную RealWorld». Неужели такое дизайнерское решение чем-то хорошо, я вот СОВЕРШЕННО не понимаю чем (эти «кишки элементов реализации наружу» мне какие-то лабораторные опытные образцы напоминают).

Резюмируя: знающие товарищи (если у вас найдётся на это время):
— поправьте меня, если я совсем не прав в своих предварительных представлениях (I.1 — I.4).
— если же мои предварительные представления о ФП «не совсем неправильные»:
— объясните как сделано — I.a — I.c
— а также какое отношение «II.a — II.d» имеет к действительности и зачем сделано именно так.

ПС
Извините за сумбур, если я недоразобрался.
Спасибо за внимание, если прочитали, и за внимание и потраченное время, если найдёте время и силы ответить!
В ПФР до 100тыр (ну там 106тыр или что-то около того) платится полная ставка (23% вроде) и с этого идёт вам пенсия.

Со всего что выше — платится 10%. И это, как бы лучше выразиться, благотворительность.
Вместо update:
Про продолжения и call/cc нашёл статью достаточно начального для меня уровня на русском (перевод):
fprog.ru/lib/ferguson-dwight-call-cc-patterns

Про cps-преобразование, эффекты (и почему монады это упрощённое call/cc) вопросы однако остались.
У вас тут такой интересный разговор, а можно ссылочку (для базового уровня, лучше на русском, чем нет), что такое cps.
Ну и сразу что есть «эффекты», что «продолжения».

Действительно вброс.
У меня там стоит увлажнитель воздуха. На момент покупки был оптимален по ТТХ под мои требования, за исключением наличия неотключаемого синего индикатора работы.
Раз уж у нас публичный «камминг аут» на тему ФП, то присоединюсь к нему.

ФП в «дельта-окрестность моего информационного поля» попало с год назад, в основном благодаря статьям на хабре / ЖЖ. Изучать его я начал 2.5 месяца назад на новогодние каникулы (и поставленных целей, на мой взгляд добился, хотя впереди ещё «типы в языках программирования» и «чисто функциональные структуры данных»).
Забавное уточнение: попытка изучить ФП пол-года назад в мультипорадигменном Python у меня провалилась (что такое map\recude\filter я и так знал, а всё остальное в Python проще написать… мультипарадигменно (*)).

По результатам скажу так: если вы не знаете ФП то не читайте (с целью получить общее представление) статьи о нём в популярных источниках, — скорее всего получите превратное понимание.
Лучше возьмите любую книгу (или курс на любом ресурсе) и изучите\пройдите до конца. Мне понравилось «изучай Хаскель во имя добра» (например 14 занимательных эссе о Хаскель куда хуже легли лично на моё понимание).

Также хотелось бы… не то, чтобы «кинуть камень в огород» функциональщиков, но предупредить начинающих:
В книге Криса Окасаки «Чисто функциональные структуры данных» прямо во введении говорится, что для ряда структур данных не существует (в ряде случаев это доказано) функциональных алгоритмов, столь же эффективных, что и «мутирующих данные» (наши обычные алгоритмы). Просто помните, что это, пожалуй, та цена, которую вы платите за всю ту красоту функционального подхода, которой вы пользуетесь.

*) Тут есть интересный вопрос: а есть ли ФП для начинающего (вопрос в том, чтобы изучить) за пределами Хаскеля? Я его не обнаружил и сложности, на мой взгляд тут вот в чём:
— по более идеоматичным ФП-языкам (agda, idris) на порядок сложнее найти вводные материалы
— для мультипарадигменных сложно выбрать хороший курс (не вида: how to use map\filter\recude) и если курс найден, дойти его до конца, искуственно ограничивая себя функциональным подходом в мультипарадигменном языке.
>> Исследование Стэнфордского университета (2014) говорит о том, что за магией стоят строгие научные выкладки.

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

Вот я беру Хаскель, пишу в нём `:k (->)` и вижу:
Prelude> :k (->)
(->) :: * -> * -> *
Но почему (->) имеет два параметра и результат (три `*`), а не один параметр и результат?

Я, видимо, не понимаю чего-то очень базового, но я «не понимаю чего именно я не понимаю» :(

Ну и второй (но скорее уже факультативный) вопрос: а зачем вообще делать функцию экземплярами классов Functor \ Applicative \ Monad?

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

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

Оспаривал-то утверждение "(помимо неопределённого размера) if внутри runtime-типизации ломает аппаратные оптимизации".

Нет не ломает (есть средства чтобы не ломались) хД
Всегда нужно валидировать и валидировать много. Это постоянные 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 строк кода для перемещения левого края и отдельная функция для каждого действия.

Information

Rating
2,288-th
Registered
Activity