Comments 133
ой, дайте мне это развидеть.
Вполне справедливое высказывание. Оверхед от иммутабильности мог сойти за аргумент в пользу языков с ручным управлением памятью.
Ну да, ну да.
А LISP как интересно существовал? На нём писались и пишутся (на диалектах) очень сложные программы.
Искренний вопрос: можете более детально объяснить, почему так?
Мне непонятно, потому что ещё в универе мне преподавали на нем ФП + я сходу не вижу почему он на считается функциональным.
JS стал перенимать функциональные штуки не так давно. Python, по моему опыту не слишком удобен в ФП. Да, в этих языках есть средства для ФП, как и во многих других, но я не понимаю как это делает Лисп не функциональным языком?
Схема ж не лисп.
Scheme — это lisp:
http://www.scheme-reports.org/Reports/r7rs.pdf
Scheme is a statically scoped and
properly tail recursive dialect of the Lisp programming lan-
guage [23] invented by Guy Lewis Steele Jr. and Gerald
Jay Sussman.
Scheme — это lisp:
"scheme же не лисп" — это такая шутка. Курица — не птица, scheme — не lisp.
Дело в том, что группа scheme-derived лиспов семантически очень сильно отличается от группы "классических лиспов", кодификатором которых является на данный момент common lisp. Эти различия намного существеннее, чем, например, между сишкой и джавой.
По-этому, когда вы говорите "чтото там лисп, но ведь scheme..." — это не особо корректно вне контекста конкретного языка. На практике нет смысла говорить о лиспах в общем.
Ну если говорить конкретно о CL vs r6rs, то общего у них скобочки и динамическая типизация, все остальное разное. CL работает внутри образа, это lisp-2 (разные пр-ва имен для ф-й и переменных), там есть свое ооп (CLOS), у них разная макросистема, стандарт CL не требует ТСО, с-но там есть примитивы для циклов, в отличии от схемы, где есть ТСО и циклы делаются через рекурсию. Вообще набор примитивов очень разный. Идеологически они очень разные — scheme более "академичный", достаточно минималистичный, мутабельные примитивы есть но их использование не приветствуется. С точки зрения общелисперов программирование на схеме — это bondage and discipline :)
В Common Lisp стандартная библиотека рассчитана на мутабельность всего и вся, не требуется и часто не делается оптимизация хвостовых вызовов, очень сильно развиты конструкции циклов, для функций высщих порядков требуется специальные конструкции.
Scheme вполне функциональный. Мутабельность там изредка используется для оптимизации, но без нее удобно обходиться.
Функции высшего порядка и функции как объекты первого класса были там изначально.
Я не топлю за ФП, просто мимо проходил и увидел странное утверждение.
Преподавали, наверно, потому что в нём есть базовые элементы ФП — лямбда-абстракция и замыкание, а также односвязный список в сердце языка. Но шаг в сторону — и появляются мутации. С комбинаторами не так удобно работать, как в языках с синтаксисом ISWYM (*ML, Haskell). С таким же успехом можно на Питоне и С++ преподавать ФП.
Так что Лиспы считаются функциональными, но примерно в той же степени, что и Питон.
Я к тому, что структуры, внешне выглядящими иммутабельными, для внутренних алгоритмов необязательно должны быть иммутабельными.
Не надо еще забывать, что затраты на сборку мусора обратно пропорциональны количеству памяти в системе.
Сейчас с дешевой памятью все на порядок лучше, чем 20 лет назад, и сборщики могут позволить себе работать быстро.
Однако в хаскеле очень много мутабельности: все ленивые вычисления реализованы через мутабельность (с точки зрения GC).
Говорят, что с помощью ленивости в хаскеле возможно реализовать даже двухсвязные и циркулярные списки, что невозможно в языке с истинной иммутабельностью (например, в Erlang).
Здесь не надо путать реализацию и семантику. Да, с точки зрения реализации ghc мутабельно перекладывает байтики. Но с точки зрения семантики программист может считать, что этого не происходит, и все работает иммутабельно, магическим образом.
Здесь как в Clean — программист пишет иммутабельный код, а компилятор при помощи сильной системы типов его оптимизирует и заменяет мутабельными операциями. Но у программиста нет никакого способа узнать, что операция прошла мутабельно (с-но, именно это система типов и гарантирует)
Во-первых, я сразу в скобочках уточнил: с точки зрения Garbage Collector. Я ведь отвечал на замечание, что "иммутабельность вообще упрощает сборку мусора".
Во-вторых, я привел пример, доказывающий, что Хаскель не истинно immutable, т.к. в понастоящему immutable языке нет возможности организовать двухсвязный список, да и вообще любую структуру с циклами.
Со вторым моментом я могу несколько ошибаться, потому что здесь многое зависит от принятых определений. Если сказать, что хаскель настолько крут, что позволяет сконструировать иммутабельную структуру с циклами, то наверное я не прав.
С точки зрения Garbage Collector — да. GC и не подозревает о том, что вы (как программист) не замечаете этой мутабельности.
Мы же рассуждаем о мутабельности с точки зрения программиста и семантики языка.
Да и точки зрения зрения GC «мутабельная ровно 1 раз» переменная от настоящей мутабельной отличается существенно, о чём было высказывание выше.
Я отвечал на замечание "иммутабельность вообще упрощает сборку мусора".
И, смотрите мой ответ https://m.habr.com/ru/post/438970/comments/?reply_to=19737594#comment_19737792
И если вы почитаете про Garbage Collector в GHC, аы узнаете, что даже "мутабельная ровно 1 раз" переменная сильно усложняет ему жизнь.
Когда я заинтересовался функциональным программированием (где-то в районе 2000 года, я тогда программировал на C код для ядра FreeBSD), я решил изучить сразу два языка, написав интерпретатор Рефал-подобного языка на Haskell. Ввод/вывод я не поддерживал, что сильно упростило задачу — через пару дней интерпретатор работал. Что меня поразило — ошибка, которую не отловил компилятор, была всего одна, в грамматике, которая генерировалась happy. Очень помогла ленивость — компилятор создавал список функций, а когда требовалась сосластья на другую функцию, я просто искал ее в этом списке, хотя она могла компилироваться позже. С монадами я тогда не разобрался — чтение программы с консоли и вывод результатов компилировал методом научного тыка.
Потом я принял небольшое участие в одном исследовательском проекте (найденом через рефаловское комьюнити). Неожиданностью было что добавление pretty print результатов в пару десятков строк увеличивало время работы с 4 до 6 минут.
Увлекаясь защитой информации, я дал простунькую программу на Haskell очень крутому реверсеру для дизассемблирования — минут через 15 он ответил Nightmare.
Потом на каком-то форуме ввязался в обсуждения моделирования rs-триггера — решение на Haskell за счет ленивости оказалось тривиальным. Оно отличалось от предлагаемых на форуме «горизонтальным временем» — я выводил состояния сигралов в каждой точке в отдельной строке. Переписывания вывода в столбик увеличило программу раза в 2.5 (хотя на больших интервалах моделирования она бы работала быстрее). Правда, потом там решили, что «горизонтальное время» больше похоже на работу с осцилографом.
Очень помогло в изучении чтение статьи The Evolution of a Haskell Programmer.
Когда меня занесло в контору, разрабатывающую микросхемы, оказалось что Haskell — идеальный язык для моделирования подобных систем. Правда, из-за ленивости, на больши интервалах начиналась утечка памяти, с которой было тяжело бороться (хотя для моделей проблема не критичная).
Далее знание Haskell мне очень помогло в освоении Scala (при этом почти не зная Java или C#). А это сейчас один из самых высокооблачиваемых языков, Scala-сеньеров на рынке расхватывают как горячие пирожки. Уже ради этого Haskell имеет смысл учить как первый язык.
Игорь Шевнин: Ленивая модель вычислений обычно помогает, но когда порядок вызова функций важен, может быть трудно разобраться, что происходит.
Когда порядок функций важен (например когда надо приготовить файл или написать в базу), вы должны въявную это указывать при помощи IO/do, что как бы и есть императивное программирование. Другое дело, что ваш Хаскель таки на ура разрешает сайд-эффекты, а далеко не каждый разработчик сможет их увидеть. И в один прекрасный момент вместо (INSERT-UPDATE) выполняется (UPDATE-INSERT), вызывая очередную головную боль.
Игорь Шевнин: Но благодаря краткости и строгости Haskell подходит почти для любых задач.
Doctor_Ryner: Зачастую сложные конструкции Haskell позволяют создавать очень короткие решения, которые еще и оказываются очень гибкими и модульными.
Короткие не значит понятные. Был такой write-only язык Perl, там тоже были короткие однострочники, в которых сам автор уже через неделю нифига не шарил.
в противовес ООП, где в мир выброшена куча объектов и объекты пытаются общаться друг с другом путем побочных эффектов, превращая приложение в непредсказуемое месиво.
В ООП мире моделируется система сущностей, наиболее приближенная к реальному миру, а также ее эволюция во времени. В ФП моделируются абстрактные преобразования над исходными данными. Но тем не менее на определенном этапе любое ФП всегда скатывается в императивное программирование, например, когда нужно осуществить системные вызовы в определенной последовательности, и именно здесь начинаются настоящие сайд-эффекты. Без этого никак.
Но мощная система типов заставляет внимательнее относиться к передаваемым значениям. Куча определений типов может выглядеть как бойлерплейт.
В том-то и дело. С одной стороны, мы хотим дать исчерпывающее описание предметной области на этапе декларации, чтобы компилятор отловил как можно больше и т.д. С другой стороны, а так ли это необходимо, и стоит ли платить за это ценой простоты и понятности кода, когда проще поставить в коде пару assert-ов или ручных приведений типов? Если учесть, что большинство сегодня вообще пишет без типов (JS, Python) и как-то худо-бедно справляется. Когда вы объясните клиенту, как моноиды и полугруппы связаны с его прибылью, тогда и поговорим за мощную систему типов.
Под андроид на Haskell будет скорее всего трудно писать, в этом случае лучше Java. А вот сервера писать на Haskell почти также удобно как и на Java.
Уже смущает слово "почти". Как только прикрутите к серверу базу данных, так у вас появится мутабельный стейт, и вся девственная чистота функций будет варварски сломана. Поэтому код потребует императивного последовательного применения изменений стейта, что не сильно будет отличаться от кода на Java + фреймворк.
Масло в огонь подливает то, что язык накладывает кучу «ограничений», не позволяет или сильно затрудняет кучу вещей, которые не вписываются в функциональную концепцию.
Ну да, это как всегда задачи виноваты, что не подходят под такой прекрасный язык.
Джон Доу: Чтобы первый элементарный проект хотя бы просто скомпилировался, ушло почти два месяца курения учебников, мануалов и туториалов по вечерам.
Прям мытарства какие-то с религиозным оттенком. На Ноде, РубиРейлсе или Спрингбуте через 5 минут уже все запустится, и работать будет не хуже. С таким же успехом можно программировать на брейнфаке и гордиться этим. Концептуальненько! Любой же нуб хочет сразу видеть что-то работающее, а уже потом разбираться с этим. На два месяца терпения ни у никого не хватит.
Денис Мирзоев: Да. Мне кажется высокомерность связана с тем, что они очень любят свой язык и расстроены его недооценённостью.
Высокомерность говорит о том, что в большинстве случаев ЧСВ — это единственная мотивация почему эти люди изучили Хаскель. Компенсируют что-то.
Вобщем, набор противоречащих мнений и отзывов. Поэтому стоит делать из Хаскеля очередного карго-культа, а из хаскелистов богов-гуру. В конце-концов, каждый мочит как он хочет.
Хаскель не меняет местами эффекты, так что
И в один прекрасный момент вместо (INSERT-UPDATE) выполняется (UPDATE-INSERT), вызывая очередную головную боль.
это невозможно.
Короткие не значит понятные.
Да, но с коротким текстом проще добиться понятности, чем с длинным.
Да, но с коротким текстом проще добиться понятности, чем с длинным.
Это не так. Можете взять какой-нибудь текст и удалить пробелы, знаки препинания, окончания слов — понятнее не станет.
Нет, это в обратную сторону работает. Если текст понятный, то он будет скорее короткий, чем длинный (при равном количестве информации).
(.).(.)
Без :t мне было сложно определить, что это тоже самое, что и инфиксный оператор «точка»:
.
, но только для функций с двумя аргументами. По мне так, когда в коде встретишь, сразу и не поймешь значение иероглифа, если ранее не встречал такую конструкцию.Если добавить пробелы или буквы, тоже понятнее не станет.
Ну и что?
Если текст понятный, то он будет скорее короткий, чем длинный (при равном количестве информации).
Выше я привел контрпример, который показывает, что это не так.
(при равном количестве информации)
Практически невозможно написать более короткий код с тем же количеством информации, если начальный код не был намеренно раздут. В том и дело. То есть фактически вы написали:
Если текст понятный, то он будет скорее короткий, чем длинный (но только в том случае, который недостижим на практике).
и именно здесь начинаются настоящие сайд-эффекты. Без этого никак.
Правильно, поэтому полезнее оказывается язык, в котором сайд-эффектами можно управлять.
Когда вы объясните клиенту, как моноиды и полугруппы связаны с его прибылью, тогда и поговорим за мощную систему типов.
Своему клиенту мы объяснили. Вы хотите, чтобы мы объяснили вашему клиенту? Вы сами не в состоянии?
Как только прикрутите к серверу базу данных, так у вас появится мутабельный стейт, и вся девственная чистота функций будет варварски сломана.
Сами себе противоречите.
через 5 минут уже все запустится
На Хаскеле меньше 5 минут. Или вы экстраполировали ошибку одного человека на всю технологию?
В ООП мире моделируется система сущностей, наиболее приближенная к реальному миру
Это может быть и заблуждение. Как я уже писал, у кого-то из мэтров программирования я встречал мнение, что на самом деле ООП исключительно плохо натягивается на реальный мир. А, ну и чтоб два раза не вставать — «С наследованием оно не натягивается вообще никак (потому что ко/контравариантность) без адовых костылей.» (С) 0xd34df00d
На Ноде,
Пишите на Ноде, в чем проблема-то? Вас страшные Хаскелисты тащат крючьями к себе, тряся монадами?
В конце-концов, каждый мочит как он хочет.
Вот эта фраза лишает смысла весь ваш комментарий.
Ну, сравнивать-то можно, очего же нет? Я правда вам скажу, что хорошие проекты на Java делаются примерно так же — путем выделения максимально чистой значимой части, убирания стейта, ну то есть примерно теми же средствами, только инструмент при этом не особо помогает.
Т.н. "вычисление" не может достать что-то из БД или не может вызвать системную функцию? И функции внутри функциональной композиции не могут иметь "действия"?
Да, я имел ввиду именно негарантированный и вообще неявный порядок вычисления, когда вы делаете сложную композицию из функций, которые внутри содержат некие действия с общим стейтом. И я так думаю, это именно те случаи, которые имел ввиду Игорь Шевнин в своей фразе.
Т.н. "вычисление" не может достать что-то из БД или не может вызвать системную функцию?
Не может (без unsafe).
И функции внутри функциональной композиции не могут иметь "действия"?
Действия могут зависеть от параметров, тогда они будут функциями, тогда их можно композить с функциями как обычные функции, но при этом не будут композиться эффекты.
Для композиции эффектов есть другие комбинаторы, похожие но композицию чистых функций.
Да, я имел ввиду именно негарантированный и вообще неявный порядок вычисления, когда вы делаете сложную композицию из функций, которые внутри содержат некие действия с общим стейтом.
Вот это как раз невозможно (возможно только если специально стрелять себе в ногу через unsafe). Неявное изменение порядка вычислений есть, но оно не вредит, а либо не имеет значения, либо помогает.
И я так думаю, это именно те случаи, которые имел ввиду Игорь Шевнин в своей фразе.
Я уверен, что нет. Иногда хочется разобраться в деталях, например, чтобы оптимизировать скорость или расход памяти, и только в этом случае ленивость сложнее императивного кода. Хотя на этот случай есть инструменты управления энергичностью и ST для локального отказа от ленивости в пользу явного управления порядком и присваиваний в обычные изменяемые переменные.
Конечно, можно обмануть тайпчекер и замаскировать нечистую функцию как чистую, тогда действительно порядок вызовов может произвольно поменяться. Но это уже разработчик виноват будет, такое везде можно сделать.
Основной смысл в разделении эффектов и возможность выразить пусть и императивную предметную область максимально типобезопасно.
Я очень даже за типы и ненавижу безтиповые языки. Однако ни одна из современных областей знаний, кроме математики, на сегодня не оперирует терминами теории категорий и гомотопической теории типов. Поэтому если внезапно удастся создать Теорию Всего (и описать ее на Хаскеле), скорей всего она так и останется теорией, ибо пользоваться ей будет бесконечно сложно.
Между прочим сам алгоритм на императивном даже безтиповом языке программирования — это тоже вариант описания предметной области. И далеко не факт, что описание при помощи системы типов будет проще и понятнее самой императивной программы. Как указал один из респондентов, система типов может быть бойлерплейтом.
Я просто делаю за три месяца то, что соседняя команда обещала сделать за 9, и у меня всё готово
Ну вот это нифига не показатель. Показателем будет, например, когда весь стек компании (или большое число разнотипных задач) переписали на Хаскель, и стоимость проекта/сроки сдачи уменьшились на столько-то.
Ну будет часть бизнес-логики жить в какой-нибудь монаде типа STM, тоже мне проблема. Зато, опыт показывает, значимая часть всё ещё будет чистой, хорошо тестируемой, композируемой и так далее.
Все данные в STM не запихаешь, а чтобы база стала STM, нужен как минимум serializable уровень изоляции. Кроме того, чтобы обеспечить чистоту, вам придется отделить все чтения от всех записей, а такая компоновка не всегда соответствует задаче — все-таки в каждом из бизнес-модулей выполняются сразу как чтения, так и записи.
А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.
Как правило в этом случае задача стоит достаточно конкретно и для ее решения хватает системы типов, предоставляемой типичным ООП-языком. Делал я как-то движок для покера, и подумал, что как раз тут пригодилась бы система типов для вычисления комбинаций. Оказывается, есть реализация на Хаскеле. Принцип более-менее понятен. Однако не могу сказать, что представленная модель сильно напоминает человеческое описание правил игры, а также, что сходный функционал на Java сильно в чем-то уступает.
Не понял, почему?
Может это вы оказались хорошим специалистов на фоне остальных, может задача была специфическая и ее эффективнее было решать на Хаскеле, может еще куча причин было. Я не слышал success stories от массового применения Хаскеля в компаниях, почему бы, если он настолько удешевляет разработку?
Почему в одной транзакции не может быть произвольного набора действий?
Для примера возьмем абстрактный регистр X и какие-нибудь два вычисления, изменяющие его значения: X := f1(X) и X := f2(X). Не важно какая реализация у X — STM, файл или строка в базе данных. Есть всего два варианта реализации транзакции:
- Все чтения X будут выдавать одно и то же значение, которое было на момент начала транзакции, а все изменения X будут видны уже после транзакции.
- Все последовательные изменения X будут видны в той же транзакции.
И оба способа плохие. В первом случае мы сразу получаем проблему "lost update". Во втором случае логика полагается на последовательное применение операций. Но поскольку в нашей функциональной программе последовательность чтений и записей не определена (или определена неявно), то это будет вести к трудноотловимым ошибкам.
А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.
Им присуща как раз динамическая типизация :)
То есть тип яблок как объекта, в рантайме, но не тип терма.
Tagless final
Кривой костыль для языков, в которые нормальных макросов не завезли ;)
1. Несовершенный мир
2. Идеализированная математическая модель
Хм… логичный выбор. Проблема в том, что эти «сущности» помещены не в реальный мир, а в никуда и просто взаимодействуют между собой побочными эффектами мутируя все подряд, моделируя приближённый к миру хаос и непредсказуемость. Насчет JS, зачем у вас там в React то иммутабельность привносят? А TypeScript и Flow? От хорошей жизни? Нормально они без типов живут (в Python вообще типы добавили), ага, достаточно спросить в чате какого это поддерживать JS приложение без типов и тестов… с тестами для тестов, вот это то конечно лучше.
Насчет IO, начнем с того, что мягко говоря многие вместо написания чистых иммутабельных функций будут писать мутабельный код с побочными эффектами, в хаскеле же напротив, IO используется исключительно только в тех случаях, когда без него просто никак. Всякие вещи на подобии взаимодействия с базами данных отделяются и отчищаются, смысл в том, что бы контролировать побочные эффекты, хаскель поощряет использование чистых функций, поэтому опять же, человек будет максимально часто писать чистый код, на других же языках обычно с этим не заморачиваются, пихнут стейта, ссылок, указателей, «не дай бог», глобальных переменных, и начинают мутировать друг друга
Проблема в том, что эти «сущности» помещены не в реальный мир, а в никуда и просто взаимодействуют между собой побочными эффектами мутируя все подряд, моделируя приближённый к миру хаос и непредсказуемость.
Сущности — это лишь компоновка общего стейта, которая может отличаться для различных парадигм. Не важно чем он представлен — записями, объектами, переменными, таблицами в базе. Весь стейт мутирует всегда предсказуемо при последовательном применении операций, что отвечает интуитивной концепции времени. В каждый момент у нас есть стабильный snapshot всей нашей вселенной. Когда речь заходит о паралельном программировании, и нарушается sequential consistency, то все-равно так или иначе всю задачу стремятся свести к последовательному выполнению, изолируя области данных (например стек) и используя уже избитые примитивы синхронизации.
Да, ООП далеко не самая лучшая парадигма, и большинство фреймворков предлагает обычное процедурное программирование даже в ООП-языках, разделяя stateful и stateless объекты.
Всякие вещи на подобии взаимодействия с базами данных отделяются и отчищаются, смысл в том, что бы контролировать побочные эффекты, хаскель поощряет использование чистых функций
Как я уже писал выше, это предполагает определенную компоновку бизнес логики: т.е. мы отделяем все чистое и вычислимое от всего грязного и "эффектного". Хорошо, если у нас более-менее однородная задача, и она вся легко перекомпонуется — все эффекты, например, можно свалить вконец операции. Но это не всегда подходит для сложных бизнес-задач, которые состоят из множества других атомарных модулей, каждый из которых содержит как вычисление, так и действие.
Она может увеличить производительность, если результаты промежуточных вычислений не будут использоваться. (К примеру head. sort
работает за линейное время).
А это сам sort за квадрат тогда работает, что ли?
Зачем? Это просто вырождается в partial sort за счёт ленивости.
Очевидно, это верно не для любого алгоритма. Например, если это квиксорт, то чтобы взять от него head — надо, с-но, выполнить весь квиксорт, целиком
Вот я попытался вспомнить какую-нибудь неквадратичную сортировку, которая в ленивом случае бы выродилась в линейный head, и не смог. Потому и вопрос.
Теперь я переписываю всё с Haskell'а на Rust. Многое уже переписал, всё летает (с тем же алгоритмом и без какой-либо оптимизации).
Обращаясь ко всем, хочу сказать следующее. Люди! Haskell — это прекрасно! Учить его полезно любому! Но если вы, как я, поймёте, что не осилили, — не расстраивайтесь: Haskell правда сложный и правда не для всех; я проверил.
Но, сейчас попробую по вашим рекоммендациям потестировать.
C++ даже сравнивать ни с чем не надо, язык ужасен. Си — хороший язык для низкоуровневой разработки.
Всё ясно с этими товарищами. После этой фразы интерес к мнению этого человека упал до нуля.
Джон Доу: Строгая сильная (я бы сказал, фашистская) типизация.
На сколько я знаю, он же православный!
Всегда удивлял спор о том, что ООП лучше ФП и т.п., так как любой иструмент удобен там, куда он предназначен. Жарить в кастрюле тоже возможно, но не всегда оправдано :)
я потерял покой и сон и нашёл Голдблатта «Топосы. Категорный анализ логики»
Для начинающих — плохая книга, автор достаточно безалаберно относится к строгости изложения.
"категории для работающего математика" Маклейна, тут без вариантов. В принципе, достаточно первых 5 глав (с решением задачек, конечно).
А Голдблатт — он интересный, но желательно его читать, уже имея хорошее представление о предмете.
Кое-какие начальные сведения о категориях есть "Не совсем наивной теории множеств" Вавилова (но там надо читать всё подряд, так что если теория множеств не интересует, то видимо это не вариант).
Ещё вот — Написал учебник теории категорий
Книга очень сложная (для проф. матматиков). Но там есть интересная мысль, автор явно пишет, что несмотря на то, что традиционно категории расматриваются "уровнем выше" нежели группы, множества, представления, и т.п. он располагает категории на том же "уровне асбтракции".
1. Плагины к эклипсу.
2. leksah
Оба рабочие, но оба не то чтобы слишком юзерфрендли. Я остановился на последнем, но по сравнению с IDE для Java это зачастую боль и страдание.
PS: если вы пользуетесь emacs, то для вас есть еще варианты, но я их в живую не видел.
HIE очень нестабилен, способен жрать очень много памяти, зато фичастый.
Ghcid наоборот же работает весьма стабильно и без особых проблем с производительностью, но фич у него минимум.
Поиск по вики есть — https://github.com/ruHaskell/ruhaskell/search?q=IDE&type=Wikis
Хотя там всего несколько страниц, можно по их списку пройтись.
А ещё можно задавать вопросы в наших чатах — https://ruhaskell.org/links.html
Не стоит забывать, что еще лет 20 назад железо было не достаточно производительным для функциональных языков, так что в мейнстрим функциональщина начала входить в последние годы, а интерес к Haskell только растет.
и
Денис Мирзоев: По скорости сравним с Java, но не такой быстрый как C.
То есть для Java двадцать лет назад производительности хватало, а для Хаскеля было мало?
Тут правда еще вопрос к 20 годам, потому что разница в производительности например Pentium II выпущенного 21 год назад и Pentium 4 (Northwood) — 17 лет назад была колоссальной
пройти курс на Coursera по Хаскелю
Какой курс имеется ввиду?
Говорят, Haskell — язык для гениев и академиков. Правда?