Сетодиод без корпуса занимает очень мало места. Над ним лепим простейшую рассеивающую свет пластинку. Миллиметров 5*5 вполне хватит для равномерного рассеяния. Если помудрить, может и 10*10. А если увлечься физикой распространения света в различных средах — можно очень крупные блестяшки делать. Но чем больше — тем темнее должно быть вокруг для их заметности, потому что закон сохранения энергии никто не отменял.
Обычный светодиод из детских игрушек светит очень ярко для освещения уровня облачного дня или в помещении. А вот на солнце нужно что-то вроде электронных чернил.
Наслышан, что в яндексе много слабых проектов. И вижу подтверждение.
Простой вопрос — а зачем всё это? Где финальная цифра? Что-то вроде «мы подняли производительность в таком-то месте на 146%». Выгода яндекса — ххх млн.р. Но вместо этого куча всякой мелочи внаброс. Без системы, без оценки. Даже что-то про «замеряйте» вроде как слышали. Но где замеры до изменений и после? Где вклад изменений? Какой-то натуральный детский сад — мы строили, строили, и вот — построили!
Но зато народ с удовольствием ковыряется в куче мелких деталей и учится экономить на спичках. Я раз за яндекс, он оправдал ожидания.
Но если бы вы этот haskell report хотя бы открыли, то увидели бы, что там и описание подробное (вполне себе на уровне плюсового стандарта, и читать его легче), включая семантику и формальный синтаксис, и вполне себе есть секция про стандартные библиотеки.
Открывал. Видел, что там не 90 (по вашему) а 300+ страниц, ага.
Ну и монады — вы видели там главу про IO? 4 страницы.
Для сравнения в той же Java exception-ам отведено 14 страниц. Только exception-ам. А в хаскеле меньше одной страницы на Exception Handling in the I/O Monad. Ну что — супер спецификация.
Взял для примера Let Expression. Выше один знаток мне писал код для отбора списков с использованием этого выражения, я ему указал на отсутствие части in, он промолчал. Я решил, что опять забыл синтаксис и полез в этот самый репорт. Ну и вижу — строчка псевдокода, 5 строчек описания, строчка с очень частным примером. И всё. Далее идёт какая-то обведённая часть с названием Translation, в ней как я понял показано преобразование конструкции к ядру языка. И всё, больше ничего про Let нету.
Вот так — 5 строчек описания.
Хотя вы конечно сможете показать, как мне там найти вариант Let Expression без части in? Либо согласитесь, что даже те, кто считают себя знатоками путаются в простейших выражениях. И сложность здесь совсем ни причём.
Ну и Java — какой-нибудь простейший Assignement Context — 5 страниц описания. Больше чем на всё IO в Report-е.
В общем если не знаете смысла спецификации — можно было хотя бы просто промолчать. А то-ж вынесли на свет божий безалаберность и нежелание хоть что-то пояснять со стороны авторов Haskell Report.
Ну а с таким подходом и Haskell без проблем учится
С любым подходом к изучению хаскеля будут проблемы.
Ещё раз — связать программу в строгую последовательность передачи параметров и вызова (ладно, условного) функций — это большой геморой. И для его устранения нужно запомнить массу шаблонов, которые нельзя забывать, потому что связность сразу потеряется.
В случае императива имеем возможность разбить обучение на независимые шаги, когда ученик получает некую основу и спокойно решает задачи соответствующего уровня. При переходе к новому совсем не обязательно, что ранее данная основа вообще понадобится. Поэтому учить можно независимыми кусками. С функциональщиной же такой фокус не пройдёт.
что за задача у вас с базами данных, что она требует массу кода для записи и совсем чуть-чуть — для чтения.
Имелась в виду работа с БД вообще. Не только запись.
вот чтение или модицикация… дело другое.
Отлично, теперь покажите отсутствие состояния при чтении, ну и при модификации.
SQL и функциональщина — очень близки (хотя и не совпадают).
Это очень разные подходы.
На SQL мы говорим, что нужно получить. На ФПЯ мы выстраиваем синтаксически правильную последовательность из аргументов и функций. Если эта последовательность получится читабельной — вы можете сказать, что стало похоже на SQL, но в большинстве случаев получается нечитабельно.
А нечитабельно потому, чтонужно зазубрить (тупо и нудно) очень много всего, начиная от синтаксиса, который на пару порядков разнообразнее SQL, и до всех тех шаблонов, которые обязательны для получения связной конструкции из функций и аргументов.
Или по другому. В ФП нельзя остановиться. В принципе нельзя до тех пор, пока не получится выходное значение. Иначе — ошибки компиляции. В императиве можно задать переменную, потом подумать, потом добавить ещё переменную, потом вынести в отдельную структуру, если показалось сложным. И каждый раз программа компилируется. Можно понемногу продвигаться к результату. В ФП же всегда нужны заглушки в виде недописанных функций. И эти функции никак не декомпозируют предметную область. Потому что область декомпозируется на элементы её состояния, а не на функции.
Вообще погуглите о проблемах с ФП в энтерпрайз разработке. Вам везде встретится проблема состояния. Точнее его отсутствия в ФП. Например — куда девать сессию при работе с браузерным клиентом? Ну и всё вот такое.
Вот объясните, просто и понятно, почему программа выводившая одно число работала, а как попытались вывести два — так сразу, почему-то, просит вызвать функцию?
Потому что вы нарушили правила, которые вам рассказывали во время урока по потокам. Не нарушали бы правила — всё бы работало.
Получается, что вы ради того самого указания на процессы течения крови в ваших жилах теперь умышленно находите примеры, требующие учёта протекания крови. А если не ставить задачи во время обучения ожидать от учащегося знаний о процессах течения крови? Тогда мы вернёмся к тому, что я написал в предыдущем посте. Поэтому попробуйте ответить как-то по другому, ведь вот так «натягивая сову на глобус» ((с) ваше), вы обязательно отобьёте желание учиться у любого ученика.
Haskell, по сравнению с этим, просто милашка.
Приведите же пример, аналогичный сишному. И мы сравним. А так — ну опять сова на глобусе.
Что же касается всего остального — то это полный бред, потому что там вы не пытатесь кого-то научить программировать на Haskell.
Я пытаюсь вам показать проблему. А учить я вас не собирался, вы ведь вроде уже не школьник?
Так это не работает. Функция не вызывается. Нет никакой «последовательности вызова функций»
Есть последовательность. Если уж вам так хочется — начнём сразу с лямбда исчисления. Ну и посмотрим на последовательность подстановок при циклическом применении правила редукции.
ИЗМЕНЕНИЕ СОСТОЯНИЯ — ЭТО ТО, О ЧЁМ ВЫ НЕ ДОЛЖНЫ ДУМАТЬ, ТАК ЖЕ, КАК ВЫ НЕ ДУМАЕТЕ О ДЫХАНИИ, когда вы пишите функциональную программу.
Я не знаю, какими аналогиями вы пользуетесь, когда пишете реальные программы, но если вы касались, ну например записи в БД, то я с нетерпением жду ваших пояснений по такому процессу, но без мыслей о состоянии. И только потом я смогу показать, почему ваш подход неэффективен.
Чтобы не сравнивать яблоки и вертолёты — не могли бы вы привести подобный же учебник C++. В котром перед тем, как вы пишите подобную программу:
#include <iostream>
using namespace std;
int main() {
int x, y;
cout << "Enter x: ";
cin >> x;
cout << "Enter y: ";
cin >> y;
cout << "Sum is " << (x+y) << std::endl;
}
Вам подробно описывают, всё, что в ней происходит. То есть:
— работу со включаемыми файлами (в том числе разницу между системными и несистемными)
— области видимости и, отдельно, пространства имён видимости и управление оными
— типы значений (glvalue, prvalue, xvalue, lvalue, и rvalue) и связанные с ними ссылки (включая разницу между Lvalue ссылками и Rvalue ссылками)
— классы, наследование (в том числе не забудьте про множестенное и виртуальное, пожалуйста, потому как без этого ж с std::ios работать не получится), и, конечно шаблоны и типажи, а также виртуальные функции (потому как cin/cout — это всё испольуют)
— разные виды инициализации (включая, статическую, динамическую и раннююю динамическую… а то вы без cin/cout останетесь)
— Перегрузка процедур и функций (включая, конечно, перегрузку операторов)
— ну и, до кучи, всякие мелочи там — фундаменталиные типы и числовые лимиты, порядок вычисления с приоритетом операций (это разные вещи, прошу не путать) и ещё десяток вещей, про которые я забыл (включая такие шедевральные вещи, как то, что функция main обазана иметь возращаемым типом int — но при этом возвращать значение в ней (и только в ней) — необязательно)
Вы логично, но неправильно, строите возражение.
Да, у каждого действия в программе есть «подноготная». Но есть нюанс. Нам не нужно знать детали, если мы уже знакомы с концепцией. Но если мы незнакомы с концепчией, то только по деталям мы выясним суть происходящего.
Так в вашем примере имеем вполне логичные стрелки, указывающие направление движения информации, плюс объявление прерменных, плюс арифметику уровня первого класса, плюс std::endl (символ конца строки вроде?). Всё это показывает нам пример модели, давно и прочно усвоенной каждым ещё до школы — берём что-то и пихаем это по стрелке. Все остальные детали совершенно не важны, ведь вам не важно, что вы не знаете, как происходит процесс дыхания, как течёт кровь, как сокращаются мышцы и как работают нейроны в момент вашего «пихания по стрелке». Вам важно одно — вы достигаете цель.
Теперь хаскель. Аналогичная по сложности программа будет выглядеть примерно так же, но уже объявление переменных придётся либо исключить, либо вводить дополнительные конструкции языка. Но как я говорил ранее — этого мало, ведь чуть шаг влево-вправо — вас расстреляет компилятор. А почему? Спросит студент. Я ведь использую привычную модель со стрелками, а он её не понимает! Вот так на очередном простом примере мы снова видим разницу. Но если пример будет чуть сложнее — вы сами обязательно согласитесь, что модель движения по стрелке сразу умрёт, потому что стрелки будут разбавлены промежуточными конструкциями с той же фильтрацией или какой-то другой логикой. А вот в сишном примере можно включить фильтрацию просто очередным шагом, совершенно не влияющим на окружающие действия. Никак не влияющим, если нет связей по переменным. В ФП же в следствии необходимости всё заворачивать в функции нам придётся добавить ещё одну зависимость — по последовательности вызова функций. Не по привычной последовтельности шагов (взял яблоко с первой полки, положил на вторую), а именно по непривычным для обычного мира способав создания зависимостей.
Ну и чем дальше в лес — тем страшнее хаскель. Ведь каждый раз мы опять и опять должны находить способы заворачивания всего на свете в функции, да так, что бы «всё было чисто». И вот этим способам и посвящена львиная доля учебника. В случае же с императивом нам не надо ничего никуда заворачивать. Мы просто берём привычную модель полок, ступенек, ящичков, корзинок и работаем с ней без всяких обёрток. Привычно, логично, доступно, просто.
Ну вы сравнили. Репорт — это поверхностное описание концепций. А стандарт языка (или спецификация) — это подробное описание всего, что касается языка. Там все алгоритмы работы каждой конструкции, плюс обязательное описание стандартных функций (они всегда есть, без них нет языка, поэтому сложно назвать их библиотечными).
Хаскель вообще вырос в условиях бесшабашной вольницы. Авторы ещё в момент обсуждения основ согласились — обязательно сделаем формальную спецификацию. И так до сих пор и не сделали. А вы сравнили те спецификации, которые люди всё-таки сделали, с тем, что лишь обещали создатели хаскеля, но чего в природе просто нет.
Нужно-нужно. Только это сотни других понятий. Посмотрите как-нибудь на курс Python (а это, вроде как считается, «простой» язык). Там будет 10-20 уроков и количество новых понятий — ничуть не меньше, чем в случае с Haskell.
Я даже больше скажу — JavaScript в его полном виде реально сложнее хаскеля вместе со всеми системами автоматического вывода доказательств вместе взятыми. Но с другой стороны — он так же реально проще в использовании новичками.
JS (как и другие императивные языки) позволяет ходить маленькими шагами. То есть нужно знать лишь циклы и массивы — вот вам и вся основа для реализация алгоритма отбора списков. Да, не самым явным образом здесь ещё участвуют переменные, плюс некое обрамление для запуска программы, плюс понимание о последовательностях действий вообще, плюс математика, плюс какая-то логика и всё такое, но это уже реально самые базовые основы, которые знают сегодня все начиная со школы (там для этого есть информатика). Главное — ограничившись малым можно реально творить что-то важное. А в хаскеле так нельзя.
Возьмём для примера монады. Почему их? Потому что программа всегда должна что-то выводить и что-то получать на вход. Поэтому любая нетривиальная программа обязана как-то работать с монадами. В императиве есть файлы и потоки — это опять небольшой шаг, сделав который, ученик мгновенно становится способным писать что-то более или менее серьёзное. А в хаскеле так просто взять и почитать про монады нельзя. Для понимания посмотрите учебник на haskell.org, называется The Haskell Wikibook. Там часть про монады состоит из 9-ти глав, и что бы перейти к той же IO монаде нужно прочитать 5 глав из этой части, а перед ней 27 глав про хаскель, включая главу, например, о функторах (явно не каждый с такими понятиями встречался). И без прочтения 27 глав вы не поймёте монады. Плюс про сами монады 9 глав. И всё это не просто так, случайность или глупость. Во всех примерах в части про монады самым активным образом используется синтаксис и приёмы работы, показанные в предыдущих главах. То есть там нельзя пропускать (ну почти нельзя). А в случае с императивом — массивы, потом циклы, потом файлы, потом потоки — всё, вы уже программист (ну почти). Никаких классов и нетривиальностей с хаскелевскими datatypes, никаких функторов, аппликативов (а это всё предки в иерархии монад). Даже в монадической части учебника монада Maybe изучается только после двух вводных глав. И это самая простейшая монада! А сколько там «very handy» костылей! Вот например один:
We have seen how (>>=) and return are very handy for...
И вот таких закорючек (абсолютно бессмысленных в угоду сокращению длины текста программы) там огромное количество. Если с потоками можно сказать ученику — отдаёшь туда байты, они дальше ложатся куда попросил, то с монадами — ну вы сами почитайте тот учебник — как и куда там байты положить, что бы они в файл попали? И со сколькими промежуточными понятиями потребуется не просто познакомиться, а тщательно зазубрить, что бы понимать, как же наши байты куда-то ложатся?
Короче — сложность есть и большая. Нужно долго и упорно писать что-то на хаскеле, либо как-то по другому зазубрить очень приличное количество материала, прежде чем можно будет что-то записать в файл. При этом ссылки на do notation не подходят, потому что чуть более сложная программа, чем просто сохранение одного массива (например с логикой типа фильтрации) уже поставят вопросы перед учеником, на которые он ответить по простому не сможет. А в императиве он уже знает циклы, знает массивы, может фильтровать явно, без использования функций, которые пока не зазубрил.
Хотя конечно, можно всё это запомнить и повторять, но вот мне лично было неинтересно убивать время на постоянное повторение и я очень многое про все эти монады уже забыл. А забыть циклы — не проблема, потому что потом можно прочитать очень немного и всё вспомнишь.
Импереативные языки — нифига не просты и с ними тяжело работать… но, конечно, если вас императивным языкам учили полгода-год (а быстрее я не видел, чтобы людей с нуля учили программированию), а на функциональные вы готовы потратиь пару часов, не больше… тогда да — функциональщина кажется сложной.
На самом деле — она просто другая.
Она не другая, она сложнее из-за необходимости решать задачки через одно узкое отверстие. Там принципиально запрещены привычные в мире вещи вроде последовательности шагов с состоянием. Всё нужно оборачивать в функции. А если сложно — вводятся новые понятия, которые нужно учить.
Проделав такое преобразование — вы сделали один шаг на пути от императивного спагетти к функциональному описанию… ничего удивительного в том, что код стал читабельнее.
Опять нет. Я раньше тоже малость глупым был — думал, что функциональщина нам дала передачу функции в качестве параметра, но потом поумнел — адрес исполняемого кода передавали ещё когда программы писали прошивкой железных переключателей. То есть суммарно функциональщина показывает пример лишь в плане способности человека находить пути извернуться даже тогда, когда он сам себе наставил массу заборов, включая внутри самого себя.
Да, они весьма креативно развили идею чистой реализации функционального подхода. Но цена, на мой взгляд, получилась слишком большой. Я не смог выучить и потом не забыть те части подхода ФП, которые нужны для написания вменяемых программ. И не могу вспомнить за пять минут, почитав что-то из серии «что такое циклы». Мне теперь опять нужно тратить приличное количество времени. Может я тупой, может память плохая, но с императивом никогда такого не было, хотя языки я менял и на новые иногда поглядываю. Одна основа в императиве позволяет мне легко переходить между разными языками. А в ФП такой основы я не нашёл.
Про поддержку в БД. А зачем ждать у моря погоды? В смысле Oracle не поддерживает фичу, значит enterprise массово не будет её использовать, а потому ждать незачем и если есть нужда — можно сделать довольно простой эмулятор, обеспечивающий аналогичный функционал без завязки на конкретную СУБД.
По сути предлагаемые решения есть именно те самые велосипеды, которые в данном случае стоит сделать самим. Потому что — всё очень жёстко заточено под конкретное видение автора велосипеда. Значит придётся изголяться и тратить много лишнего времени на получение нужного функционала через узкое отверстие, оставленное автором как обычно — сзади. А альтернатив нет (кроме собственного велосипеда). Ну и Oracle не поддерживает.
Хотя может у приведённых примеров решений есть какие-то значимые плюсы? Но я в статье их не увидел.
вы, условно, зачем-то требуете чуть ли не формально математического понимания монад, чтобы написать немного кода в IO, но не требуете аналогичных вещей для императивных языков
Проблема в том, что для написания программ на хаскеле реально нужно понимать монады. Пусть без математической мути, но зато все концепции, вроде аппликативов и прочих функторов, разбавленные массой шаблонов реализации стандартных алгоритмов (которых в хаскеле вообще тьма — там почти всё, что придумало человечество в области универсальных алгоритмов). А ещё масса сложностей с типами. Опять же — ленивость. Ну и сам синтаксис хаскеля очень разнообразен. Хотя на фоне сотни базовых алгоритмов, запомнить полсотни базовых вариаций синтаксиса, это уже приемлемо, но тем не менее — это всё нужно отлично знать, что бы писать что-то вменяемое на хаскеле (или другом языке, но именно в чистом функциональном стиле).
Вам сложно понять простую истину — вы уже знаете несколько сотен базовых алгоритмов, шаблонов и прочих закорючек из мира ФП, а тем кто начинает, сотня новых шаблонов — это смерть. Они просто говорят — зачем мне это? Я могу делать то же самое без этой мути. И реально могут. И нет необходимости запоминать сотни нетривиальных понятий. Может они в итоге не смогут креативно упростить модель некой области до уровне «нелапшекод», но тем не менее они свою копейку зарабатывают и вполне довольны. И не видят смысла усложнять. Потому что деньгами это никак не поддерживается. Они и так на пошлом Го сотни штук зелени в год рубят.
Хотя проблема стандартная, гошники тоже так как вы считают — если я понимаю, значит все остальные либо дураки, либо конкретно я — ну очень умный. В обоих случаях имеем вознесение чсв до небес. А понимания не имеем.
Код на джаве он не понял совсем за какое-то разумное время, код на хаскеле выше — «ну, тут что-то фильтруется по условию сравнения с нулём, да?»
Прочитать слово filter и подумать о фильтрации — о да, это было совсем неочевидное предположение!
Вам самому-то опять не стыдно такое говорить?
Хотя по другому — в приведённых примерах используется библиотечная функция filter, поэтому я тоже считаю себя в праве использовать библиотечные функции, значит я тоже могу написать что-то вроде filter(list,Enum.LessThanZero) — вы спросите у отца, он наверняка такой вариант сразу поймёт, ну а ваш довод с отцом сразу померкнет.
Я сначала увидел код, а не описание задачи, попытался порассуждать об этом коде и что он делает, но у меня не получилось
Вот — вы почувствовали себя немного в шкуре того, кто учит хаскель.
Но лишь немного. Потому что непривычных вам понятий было мало. А в хаскеле — всё непривычное. Поэтому его и считают сложным большинство программистов. И не изучают. А что бы изучить, нужна какая-то серьёзная мотивация. Мало у кого её хватает.
А что касается и ваших и остальных возражений про якобы необходимость учить много фич императивного языка, то повторю — всё это очень простые вещи. Я бы мог для большей простоты вместо списков использовать массив, мог бы убрать типизацию элементов, мог бы и цикл в виде (i=0;i<;i++) сделать, но это всё конструкции одного порядка сложности, а в хаскеле уровень простейшей функции сразу требует гораздо более сложных абстракций. Поэтому перечисление названий использованных мною элементов синтаксиса ни в какое сравнение не идёт с перечислением обязательных для свободного владения концепций, без которых не написать даже самую простую программу на хаскеле.
А вообще — стыдно совать в нос определения типа «что такое буква» и заявлять что-нибудь такое — а монады в хаскеле ничуть не сложнее. Это говорит либо о полном непонимании вопроса, либо о самой очевидной предвзятости. И оба варианта — хуже!
А перед этим — что такое переменная (и с усвоением этого понятия у людей действительно часто большие проблемы), отличие от константы, понятие о последовательном исполнении, оператор new и понятие конструктора, понятие типа и обобщённого типа, методы, понятие об объектах и интерфейсах, чтобы объяснить, чем отличается List от ArrayList, условный оператор, оператор continue, метка цикла.
О да, только давайте уже не мелочиться, а сразу добавим сюда — что такое компьютер, что такое число, что такое отрицательное, и т.д. и т.п. Ну а потом заявим — студентам ФП это всё совсем не надо. Ага.
Можно детальнее разобрать ваш выпад, но и так очевидно — вы явно перегибаете и делаете из мухи слона с одной целью — спасти репутацию. Но поздно.
В случае функциональщины:
1) Все пункты из императива.
Не все.
Да все, все подряд. Что там за буквочки и что они значат — вот это всё основывается на тех самых концепциях. И эти основы универсальны, никакой студент не бросится изучать функциональщину, не понимая, что такое цикл, переменная и т.д.
Про main и в императивщине рассказать надо, вы же не в вакууме код запускаете. А там сразу возникнет и пресловутый public static void, и String[] args, которые тоже придётся или объяснять, или говорить «пиши, так надо, объясню позже».
Симметрично и для ФП нужно много чего дополнительного, что бы ваш код заработал. Так что вы опять и исключительно спасаете репутацию уходом в сторону от сути.
2.1) Функции с неполным набором аргументов
Можно и без каррирования, только зачем писать копию уже готовой filter?
Только вы же не против, что студент обязан изучить все эти готовые функции? И только после изучения десятков четырёх-пяти этих занимательных созданий, студент начнёт понимать, что вообще с ними можно делать.
2.2) Лямбда-функции.
Их тут нет.
Ну конечно есть. Вы их не видите, поэтому вам кажется, что их нет. А они есть.
В любом учебнике по хаскелю постоянно звучит одна песня — изучайте исходники. Массу библиотечных функций разбирают специально, что бы студент хоть что-то понял. Ну и разумеется, без передачи безымянных функций это всё никак и никогда не обходится.
Хотя вы можете доказать обратное — напишите код без библиотечных функций. И тогда я соглашусь, что лямбд там нет (если не будете использовать). Но пока вы используете чужое — я уверен, что вы просто не знаете, как оно внутри работает (во всех деталях, включая наличие или отсутствие там лямбд).
2.3) Ну и собственно объявление (в императиве его не потребовалось).
let filtered = filter (all (>= 0)) list
Ага, вот вы внесли ещё десяток головоломок для студента. Конструкция let сама по себе нетривиальна для начинающих, а тут ещё вроде как in забыт (давно я хаскелем баловался).
И кстати, в вашем начальном варианте нет аргумента list. Тут два варианта — либо используется очередной и совершенно неочевидный механизм для неявной передачи параметров (на столько неочевидный, что я его забыл), либо вы ошиблись, доказав наличие той самой сложности.
3) Что такое рекурсия.
4) Как с помощью рекурсии решаются ряд стандартных задач
Чтобы объяснить работу filter и all, объяснять их через рекурсию ненужно.
Повторюсь про то, о чём пишут во всех учебниках — читайте исходники. И как их понять без рекурсии? Хотя вы можете привести исходники filter и all, тогда станет очевидно, что я далеко не на все грабли для студентов указал.
5) Какие библиотечные функции решают конкретные алгоритмические задачи.
Угу, а составлять filter самому из говна и палок цикла с досрочным переходом на следующую итерацию и условного оператора — это сильно проще, ага.
Конечно проще. Это не требует всего того набора дополнительных понятий, про которые я вам тут доступно разъясняю. Хотя наверняка в каких-то либах есть функция итерации по вложенным спискам и я бы мог использовать её, ссылаясь на «не составлять самому», но проблема в том, что изучать все возможные либы — очень долго. И даже один Prelude — это реально много для студента. А в моём случае — всё быстро и тривиально. Ну а про нечистоты — тут уже ваш непонятный многим код напрашивается на комплимент.
6) Как комбинировать библиотечные функции для решения нестандартных задач.
А комбинировать операторы в императивщине, разумеется, не надо.
Разумеется, их там комбинировать намного проще. Там требуется школьная алгебра где-то класс за 4, максимум пятый. А в хаскеле требуется изучение массы понятий с нуля. Есть разница?
В Basic есть динамические списки?
Я вас удивлю, но версий басика в мире уже наверное больше, чем букв в Haskell Report 2010.
Если я захочу в коде на Haskell, скажем, просуммировать все подсписки, то я добавляю эту операцию — не обязательно в эту же функцию — и у меня всё ещё остаётся один проход по списку.
Ну про проходы по списку вообще зря заговорили. В моём случае в среднем имеем половинное количество операций от вашего кода, потому что отсеивание прерывается и сразу происходит добавление, а у вас обязателен полный проход по списку.
А какую там функцию кто-то может добавить — это вообще не в кассу. Кто-то всегда что-то может, но вот если разговор пойдёт о конкретной реализации, только тогда я вам смогу что-то ответить, а не в случае когда кто-то что-то и совершенно непонятно зачем.
Итак, что должен понимать пишущий указанный алгоритм разработчик?
В случае императива:
1) Что такое список, операции с ним.
2) Что такое цикл по элементам списка.
В случае функциональщины:
1) Все пункты из императива.
2) Определение функции, включая
2.1) Функции с неполным набором аргументов.
2.2) Лямбда-функции.
2.3) Ну и собственно объявление (в императиве его не потребовалось).
3) Что такое рекурсия.
4) Как с помощью рекурсии решаются ряд стандартных задач.
5) Какие библиотечные функции решают конкретные алгоритмические задачи.
6) Как комбинировать библиотечные функции для решения нестандартных задач.
Собственно вот на простейшем примере мы видим «скромное» различие в количестве приседаний, которые должен совершить студент, изучающий хаскель против любого императива. В данном конкретном случае язык Basic вообще убил бы по простоте всех, но мы же «большие задачи» решать собрались? Поэтому императивный язык может быть чуть посложнее. А вот хаскель и вообще функциональщина проще быть не может.
Поэтому всё, что остаётся функциональщикам — убеждать мир в ценности использования кратких названий (типа функция f, ага). Но в императиве я могу круче:
Ну а сейчас очевидно ненужное многословие. Ладно, умного учить — только портить.
В общем давайте простой примерчик проанализируем. Допустим нужно выбрать списки, не содержащие отрицательных чисел. На входе список списков, на выходе тоже список списков. Во вложенных списках — целые числа.
Вот императив:
List<List<Integer>> in;
... // fill it
List<List<Integer>> out=new ArrayList<List<Integer>>();
top:
for (List<Integer> l:in)
{
for (Integer x:l)
if (x<0) continue top;
out.add(l);
}
Приведите аналог на хаскеле, сравним, покажу пальцем, где сложность.
Удивлён, как легко слились все эти фанаты Vue, React и прочих Angular. Вас всех опустили на самое днище, но вы и сказать-то в ответ ничего не смогли! Занятно :)
Но всё было бы совсем по другому, возьмись автор клеветать на функциональщину! А ведь она реально того заслуживает. Но группа её фанатов гораздо более агрессивна и сплочена, а потому автор убежал бы от них поджав хвост и опустившись в карме позиций этак на 100.
Интересный вывод — в джаваскриптёры идут слабаки. Или нет? А вот функциональщиной занимаются крайне упорные ботаники, способные залить миллионом негативных комментариев любую попытку их немного успокоить. Ну и с миллиона аккакунтов залить карму автора минусами. Учитесь, скрипто-слабаки! Вот так зарабатывают себе место под солнцем.
Обычный светодиод из детских игрушек светит очень ярко для освещения уровня облачного дня или в помещении. А вот на солнце нужно что-то вроде электронных чернил.
Простой вопрос — а зачем всё это? Где финальная цифра? Что-то вроде «мы подняли производительность в таком-то месте на 146%». Выгода яндекса — ххх млн.р. Но вместо этого куча всякой мелочи внаброс. Без системы, без оценки. Даже что-то про «замеряйте» вроде как слышали. Но где замеры до изменений и после? Где вклад изменений? Какой-то натуральный детский сад — мы строили, строили, и вот — построили!
Но зато народ с удовольствием ковыряется в куче мелких деталей и учится экономить на спичках. Я раз за яндекс, он оправдал ожидания.
Открывал. Видел, что там не 90 (по вашему) а 300+ страниц, ага.
Ну и монады — вы видели там главу про IO? 4 страницы.
Для сравнения в той же Java exception-ам отведено 14 страниц. Только exception-ам. А в хаскеле меньше одной страницы на Exception Handling in the I/O Monad. Ну что — супер спецификация.
Взял для примера Let Expression. Выше один знаток мне писал код для отбора списков с использованием этого выражения, я ему указал на отсутствие части in, он промолчал. Я решил, что опять забыл синтаксис и полез в этот самый репорт. Ну и вижу — строчка псевдокода, 5 строчек описания, строчка с очень частным примером. И всё. Далее идёт какая-то обведённая часть с названием Translation, в ней как я понял показано преобразование конструкции к ядру языка. И всё, больше ничего про Let нету.
Вот так — 5 строчек описания.
Хотя вы конечно сможете показать, как мне там найти вариант Let Expression без части in? Либо согласитесь, что даже те, кто считают себя знатоками путаются в простейших выражениях. И сложность здесь совсем ни причём.
Ну и Java — какой-нибудь простейший Assignement Context — 5 страниц описания. Больше чем на всё IO в Report-е.
В общем если не знаете смысла спецификации — можно было хотя бы просто промолчать. А то-ж вынесли на свет божий безалаберность и нежелание хоть что-то пояснять со стороны авторов Haskell Report.
С любым подходом к изучению хаскеля будут проблемы.
Ещё раз — связать программу в строгую последовательность передачи параметров и вызова (ладно, условного) функций — это большой геморой. И для его устранения нужно запомнить массу шаблонов, которые нельзя забывать, потому что связность сразу потеряется.
В случае императива имеем возможность разбить обучение на независимые шаги, когда ученик получает некую основу и спокойно решает задачи соответствующего уровня. При переходе к новому совсем не обязательно, что ранее данная основа вообще понадобится. Поэтому учить можно независимыми кусками. С функциональщиной же такой фокус не пройдёт.
Имелась в виду работа с БД вообще. Не только запись.
Отлично, теперь покажите отсутствие состояния при чтении, ну и при модификации.
Это очень разные подходы.
На SQL мы говорим, что нужно получить. На ФПЯ мы выстраиваем синтаксически правильную последовательность из аргументов и функций. Если эта последовательность получится читабельной — вы можете сказать, что стало похоже на SQL, но в большинстве случаев получается нечитабельно.
А нечитабельно потому, чтонужно зазубрить (тупо и нудно) очень много всего, начиная от синтаксиса, который на пару порядков разнообразнее SQL, и до всех тех шаблонов, которые обязательны для получения связной конструкции из функций и аргументов.
Или по другому. В ФП нельзя остановиться. В принципе нельзя до тех пор, пока не получится выходное значение. Иначе — ошибки компиляции. В императиве можно задать переменную, потом подумать, потом добавить ещё переменную, потом вынести в отдельную структуру, если показалось сложным. И каждый раз программа компилируется. Можно понемногу продвигаться к результату. В ФП же всегда нужны заглушки в виде недописанных функций. И эти функции никак не декомпозируют предметную область. Потому что область декомпозируется на элементы её состояния, а не на функции.
Вообще погуглите о проблемах с ФП в энтерпрайз разработке. Вам везде встретится проблема состояния. Точнее его отсутствия в ФП. Например — куда девать сессию при работе с браузерным клиентом? Ну и всё вот такое.
Потому что вы нарушили правила, которые вам рассказывали во время урока по потокам. Не нарушали бы правила — всё бы работало.
Получается, что вы ради того самого указания на процессы течения крови в ваших жилах теперь умышленно находите примеры, требующие учёта протекания крови. А если не ставить задачи во время обучения ожидать от учащегося знаний о процессах течения крови? Тогда мы вернёмся к тому, что я написал в предыдущем посте. Поэтому попробуйте ответить как-то по другому, ведь вот так «натягивая сову на глобус» ((с) ваше), вы обязательно отобьёте желание учиться у любого ученика.
Приведите же пример, аналогичный сишному. И мы сравним. А так — ну опять сова на глобусе.
Я пытаюсь вам показать проблему. А учить я вас не собирался, вы ведь вроде уже не школьник?
Есть последовательность. Если уж вам так хочется — начнём сразу с лямбда исчисления. Ну и посмотрим на последовательность подстановок при циклическом применении правила редукции.
Я не знаю, какими аналогиями вы пользуетесь, когда пишете реальные программы, но если вы касались, ну например записи в БД, то я с нетерпением жду ваших пояснений по такому процессу, но без мыслей о состоянии. И только потом я смогу показать, почему ваш подход неэффективен.
Вы логично, но неправильно, строите возражение.
Да, у каждого действия в программе есть «подноготная». Но есть нюанс. Нам не нужно знать детали, если мы уже знакомы с концепцией. Но если мы незнакомы с концепчией, то только по деталям мы выясним суть происходящего.
Так в вашем примере имеем вполне логичные стрелки, указывающие направление движения информации, плюс объявление прерменных, плюс арифметику уровня первого класса, плюс std::endl (символ конца строки вроде?). Всё это показывает нам пример модели, давно и прочно усвоенной каждым ещё до школы — берём что-то и пихаем это по стрелке. Все остальные детали совершенно не важны, ведь вам не важно, что вы не знаете, как происходит процесс дыхания, как течёт кровь, как сокращаются мышцы и как работают нейроны в момент вашего «пихания по стрелке». Вам важно одно — вы достигаете цель.
Теперь хаскель. Аналогичная по сложности программа будет выглядеть примерно так же, но уже объявление переменных придётся либо исключить, либо вводить дополнительные конструкции языка. Но как я говорил ранее — этого мало, ведь чуть шаг влево-вправо — вас расстреляет компилятор. А почему? Спросит студент. Я ведь использую привычную модель со стрелками, а он её не понимает! Вот так на очередном простом примере мы снова видим разницу. Но если пример будет чуть сложнее — вы сами обязательно согласитесь, что модель движения по стрелке сразу умрёт, потому что стрелки будут разбавлены промежуточными конструкциями с той же фильтрацией или какой-то другой логикой. А вот в сишном примере можно включить фильтрацию просто очередным шагом, совершенно не влияющим на окружающие действия. Никак не влияющим, если нет связей по переменным. В ФП же в следствии необходимости всё заворачивать в функции нам придётся добавить ещё одну зависимость — по последовательности вызова функций. Не по привычной последовтельности шагов (взял яблоко с первой полки, положил на вторую), а именно по непривычным для обычного мира способав создания зависимостей.
Ну и чем дальше в лес — тем страшнее хаскель. Ведь каждый раз мы опять и опять должны находить способы заворачивания всего на свете в функции, да так, что бы «всё было чисто». И вот этим способам и посвящена львиная доля учебника. В случае же с императивом нам не надо ничего никуда заворачивать. Мы просто берём привычную модель полок, ступенек, ящичков, корзинок и работаем с ней без всяких обёрток. Привычно, логично, доступно, просто.
Ну вы сравнили. Репорт — это поверхностное описание концепций. А стандарт языка (или спецификация) — это подробное описание всего, что касается языка. Там все алгоритмы работы каждой конструкции, плюс обязательное описание стандартных функций (они всегда есть, без них нет языка, поэтому сложно назвать их библиотечными).
Хаскель вообще вырос в условиях бесшабашной вольницы. Авторы ещё в момент обсуждения основ согласились — обязательно сделаем формальную спецификацию. И так до сих пор и не сделали. А вы сравнили те спецификации, которые люди всё-таки сделали, с тем, что лишь обещали создатели хаскеля, но чего в природе просто нет.
Я даже больше скажу — JavaScript в его полном виде реально сложнее хаскеля вместе со всеми системами автоматического вывода доказательств вместе взятыми. Но с другой стороны — он так же реально проще в использовании новичками.
JS (как и другие императивные языки) позволяет ходить маленькими шагами. То есть нужно знать лишь циклы и массивы — вот вам и вся основа для реализация алгоритма отбора списков. Да, не самым явным образом здесь ещё участвуют переменные, плюс некое обрамление для запуска программы, плюс понимание о последовательностях действий вообще, плюс математика, плюс какая-то логика и всё такое, но это уже реально самые базовые основы, которые знают сегодня все начиная со школы (там для этого есть информатика). Главное — ограничившись малым можно реально творить что-то важное. А в хаскеле так нельзя.
Возьмём для примера монады. Почему их? Потому что программа всегда должна что-то выводить и что-то получать на вход. Поэтому любая нетривиальная программа обязана как-то работать с монадами. В императиве есть файлы и потоки — это опять небольшой шаг, сделав который, ученик мгновенно становится способным писать что-то более или менее серьёзное. А в хаскеле так просто взять и почитать про монады нельзя. Для понимания посмотрите учебник на haskell.org, называется The Haskell Wikibook. Там часть про монады состоит из 9-ти глав, и что бы перейти к той же IO монаде нужно прочитать 5 глав из этой части, а перед ней 27 глав про хаскель, включая главу, например, о функторах (явно не каждый с такими понятиями встречался). И без прочтения 27 глав вы не поймёте монады. Плюс про сами монады 9 глав. И всё это не просто так, случайность или глупость. Во всех примерах в части про монады самым активным образом используется синтаксис и приёмы работы, показанные в предыдущих главах. То есть там нельзя пропускать (ну почти нельзя). А в случае с императивом — массивы, потом циклы, потом файлы, потом потоки — всё, вы уже программист (ну почти). Никаких классов и нетривиальностей с хаскелевскими datatypes, никаких функторов, аппликативов (а это всё предки в иерархии монад). Даже в монадической части учебника монада Maybe изучается только после двух вводных глав. И это самая простейшая монада! А сколько там «very handy» костылей! Вот например один:
И вот таких закорючек (абсолютно бессмысленных в угоду сокращению длины текста программы) там огромное количество. Если с потоками можно сказать ученику — отдаёшь туда байты, они дальше ложатся куда попросил, то с монадами — ну вы сами почитайте тот учебник — как и куда там байты положить, что бы они в файл попали? И со сколькими промежуточными понятиями потребуется не просто познакомиться, а тщательно зазубрить, что бы понимать, как же наши байты куда-то ложатся?
Короче — сложность есть и большая. Нужно долго и упорно писать что-то на хаскеле, либо как-то по другому зазубрить очень приличное количество материала, прежде чем можно будет что-то записать в файл. При этом ссылки на do notation не подходят, потому что чуть более сложная программа, чем просто сохранение одного массива (например с логикой типа фильтрации) уже поставят вопросы перед учеником, на которые он ответить по простому не сможет. А в императиве он уже знает циклы, знает массивы, может фильтровать явно, без использования функций, которые пока не зазубрил.
Хотя конечно, можно всё это запомнить и повторять, но вот мне лично было неинтересно убивать время на постоянное повторение и я очень многое про все эти монады уже забыл. А забыть циклы — не проблема, потому что потом можно прочитать очень немного и всё вспомнишь.
Она не другая, она сложнее из-за необходимости решать задачки через одно узкое отверстие. Там принципиально запрещены привычные в мире вещи вроде последовательности шагов с состоянием. Всё нужно оборачивать в функции. А если сложно — вводятся новые понятия, которые нужно учить.
Опять нет. Я раньше тоже малость глупым был — думал, что функциональщина нам дала передачу функции в качестве параметра, но потом поумнел — адрес исполняемого кода передавали ещё когда программы писали прошивкой железных переключателей. То есть суммарно функциональщина показывает пример лишь в плане способности человека находить пути извернуться даже тогда, когда он сам себе наставил массу заборов, включая внутри самого себя.
Да, они весьма креативно развили идею чистой реализации функционального подхода. Но цена, на мой взгляд, получилась слишком большой. Я не смог выучить и потом не забыть те части подхода ФП, которые нужны для написания вменяемых программ. И не могу вспомнить за пять минут, почитав что-то из серии «что такое циклы». Мне теперь опять нужно тратить приличное количество времени. Может я тупой, может память плохая, но с императивом никогда такого не было, хотя языки я менял и на новые иногда поглядываю. Одна основа в императиве позволяет мне легко переходить между разными языками. А в ФП такой основы я не нашёл.
По сути предлагаемые решения есть именно те самые велосипеды, которые в данном случае стоит сделать самим. Потому что — всё очень жёстко заточено под конкретное видение автора велосипеда. Значит придётся изголяться и тратить много лишнего времени на получение нужного функционала через узкое отверстие, оставленное автором как обычно — сзади. А альтернатив нет (кроме собственного велосипеда). Ну и Oracle не поддерживает.
Хотя может у приведённых примеров решений есть какие-то значимые плюсы? Но я в статье их не увидел.
Проблема в том, что для написания программ на хаскеле реально нужно понимать монады. Пусть без математической мути, но зато все концепции, вроде аппликативов и прочих функторов, разбавленные массой шаблонов реализации стандартных алгоритмов (которых в хаскеле вообще тьма — там почти всё, что придумало человечество в области универсальных алгоритмов). А ещё масса сложностей с типами. Опять же — ленивость. Ну и сам синтаксис хаскеля очень разнообразен. Хотя на фоне сотни базовых алгоритмов, запомнить полсотни базовых вариаций синтаксиса, это уже приемлемо, но тем не менее — это всё нужно отлично знать, что бы писать что-то вменяемое на хаскеле (или другом языке, но именно в чистом функциональном стиле).
Вам сложно понять простую истину — вы уже знаете несколько сотен базовых алгоритмов, шаблонов и прочих закорючек из мира ФП, а тем кто начинает, сотня новых шаблонов — это смерть. Они просто говорят — зачем мне это? Я могу делать то же самое без этой мути. И реально могут. И нет необходимости запоминать сотни нетривиальных понятий. Может они в итоге не смогут креативно упростить модель некой области до уровне «нелапшекод», но тем не менее они свою копейку зарабатывают и вполне довольны. И не видят смысла усложнять. Потому что деньгами это никак не поддерживается. Они и так на пошлом Го сотни штук зелени в год рубят.
Хотя проблема стандартная, гошники тоже так как вы считают — если я понимаю, значит все остальные либо дураки, либо конкретно я — ну очень умный. В обоих случаях имеем вознесение чсв до небес. А понимания не имеем.
Прочитать слово filter и подумать о фильтрации — о да, это было совсем неочевидное предположение!
Вам самому-то опять не стыдно такое говорить?
Хотя по другому — в приведённых примерах используется библиотечная функция filter, поэтому я тоже считаю себя в праве использовать библиотечные функции, значит я тоже могу написать что-то вроде filter(list,Enum.LessThanZero) — вы спросите у отца, он наверняка такой вариант сразу поймёт, ну а ваш довод с отцом сразу померкнет.
Вот — вы почувствовали себя немного в шкуре того, кто учит хаскель.
Но лишь немного. Потому что непривычных вам понятий было мало. А в хаскеле — всё непривычное. Поэтому его и считают сложным большинство программистов. И не изучают. А что бы изучить, нужна какая-то серьёзная мотивация. Мало у кого её хватает.
А что касается и ваших и остальных возражений про якобы необходимость учить много фич императивного языка, то повторю — всё это очень простые вещи. Я бы мог для большей простоты вместо списков использовать массив, мог бы убрать типизацию элементов, мог бы и цикл в виде (i=0;i<;i++) сделать, но это всё конструкции одного порядка сложности, а в хаскеле уровень простейшей функции сразу требует гораздо более сложных абстракций. Поэтому перечисление названий использованных мною элементов синтаксиса ни в какое сравнение не идёт с перечислением обязательных для свободного владения концепций, без которых не написать даже самую простую программу на хаскеле.
А вообще — стыдно совать в нос определения типа «что такое буква» и заявлять что-нибудь такое — а монады в хаскеле ничуть не сложнее. Это говорит либо о полном непонимании вопроса, либо о самой очевидной предвзятости. И оба варианта — хуже!
О да, только давайте уже не мелочиться, а сразу добавим сюда — что такое компьютер, что такое число, что такое отрицательное, и т.д. и т.п. Ну а потом заявим — студентам ФП это всё совсем не надо. Ага.
Можно детальнее разобрать ваш выпад, но и так очевидно — вы явно перегибаете и делаете из мухи слона с одной целью — спасти репутацию. Но поздно.
Да все, все подряд. Что там за буквочки и что они значат — вот это всё основывается на тех самых концепциях. И эти основы универсальны, никакой студент не бросится изучать функциональщину, не понимая, что такое цикл, переменная и т.д.
Симметрично и для ФП нужно много чего дополнительного, что бы ваш код заработал. Так что вы опять и исключительно спасаете репутацию уходом в сторону от сути.
Только вы же не против, что студент обязан изучить все эти готовые функции? И только после изучения десятков четырёх-пяти этих занимательных созданий, студент начнёт понимать, что вообще с ними можно делать.
Ну конечно есть. Вы их не видите, поэтому вам кажется, что их нет. А они есть.
В любом учебнике по хаскелю постоянно звучит одна песня — изучайте исходники. Массу библиотечных функций разбирают специально, что бы студент хоть что-то понял. Ну и разумеется, без передачи безымянных функций это всё никак и никогда не обходится.
Хотя вы можете доказать обратное — напишите код без библиотечных функций. И тогда я соглашусь, что лямбд там нет (если не будете использовать). Но пока вы используете чужое — я уверен, что вы просто не знаете, как оно внутри работает (во всех деталях, включая наличие или отсутствие там лямбд).
Ага, вот вы внесли ещё десяток головоломок для студента. Конструкция let сама по себе нетривиальна для начинающих, а тут ещё вроде как in забыт (давно я хаскелем баловался).
И кстати, в вашем начальном варианте нет аргумента list. Тут два варианта — либо используется очередной и совершенно неочевидный механизм для неявной передачи параметров (на столько неочевидный, что я его забыл), либо вы ошиблись, доказав наличие той самой сложности.
Повторюсь про то, о чём пишут во всех учебниках — читайте исходники. И как их понять без рекурсии? Хотя вы можете привести исходники filter и all, тогда станет очевидно, что я далеко не на все грабли для студентов указал.
Конечно проще. Это не требует всего того набора дополнительных понятий, про которые я вам тут доступно разъясняю. Хотя наверняка в каких-то либах есть функция итерации по вложенным спискам и я бы мог использовать её, ссылаясь на «не составлять самому», но проблема в том, что изучать все возможные либы — очень долго. И даже один Prelude — это реально много для студента. А в моём случае — всё быстро и тривиально. Ну а про нечистоты — тут уже ваш непонятный многим код напрашивается на комплимент.
Разумеется, их там комбинировать намного проще. Там требуется школьная алгебра где-то класс за 4, максимум пятый. А в хаскеле требуется изучение массы понятий с нуля. Есть разница?
Я вас удивлю, но версий басика в мире уже наверное больше, чем букв в Haskell Report 2010.
Ну про проходы по списку вообще зря заговорили. В моём случае в среднем имеем половинное количество операций от вашего кода, потому что отсеивание прерывается и сразу происходит добавление, а у вас обязателен полный проход по списку.
А какую там функцию кто-то может добавить — это вообще не в кассу. Кто-то всегда что-то может, но вот если разговор пойдёт о конкретной реализации, только тогда я вам смогу что-то ответить, а не в случае когда кто-то что-то и совершенно непонятно зачем.
В случае императива:
1) Что такое список, операции с ним.
2) Что такое цикл по элементам списка.
В случае функциональщины:
1) Все пункты из императива.
2) Определение функции, включая
2.1) Функции с неполным набором аргументов.
2.2) Лямбда-функции.
2.3) Ну и собственно объявление (в императиве его не потребовалось).
3) Что такое рекурсия.
4) Как с помощью рекурсии решаются ряд стандартных задач.
5) Какие библиотечные функции решают конкретные алгоритмические задачи.
6) Как комбинировать библиотечные функции для решения нестандартных задач.
Собственно вот на простейшем примере мы видим «скромное» различие в количестве приседаний, которые должен совершить студент, изучающий хаскель против любого императива. В данном конкретном случае язык Basic вообще убил бы по простоте всех, но мы же «большие задачи» решать собрались? Поэтому императивный язык может быть чуть посложнее. А вот хаскель и вообще функциональщина проще быть не может.
Поэтому всё, что остаётся функциональщикам — убеждать мир в ценности использования кратких названий (типа функция f, ага). Но в императиве я могу круче:
Ну если захочу повыпендриваться, конечно.
В общем давайте простой примерчик проанализируем. Допустим нужно выбрать списки, не содержащие отрицательных чисел. На входе список списков, на выходе тоже список списков. Во вложенных списках — целые числа.
Вот императив:
Приведите аналог на хаскеле, сравним, покажу пальцем, где сложность.
Но вы не с меня это всё вытягивайте, а с автора. Он ведь смелый против слабаков. Может вам чего подскажет.
ЗЫ. А накидайте мне плюсов — смогу чаще отвечать. Ведь вашей целю не является заткнуть рот возражениям, правильно?
Но всё было бы совсем по другому, возьмись автор клеветать на функциональщину! А ведь она реально того заслуживает. Но группа её фанатов гораздо более агрессивна и сплочена, а потому автор убежал бы от них поджав хвост и опустившись в карме позиций этак на 100.
Интересный вывод — в джаваскриптёры идут слабаки. Или нет? А вот функциональщиной занимаются крайне упорные ботаники, способные залить миллионом негативных комментариев любую попытку их немного успокоить. Ну и с миллиона аккакунтов залить карму автора минусами. Учитесь, скрипто-слабаки! Вот так зарабатывают себе место под солнцем.