Говорят, Haskell — язык для гениев и академиков. Правда?



    Однажды я разговаривал с основателем израильского стартапа, который разрабатывал скоростную базу данных на GPU. В их стеке были Haskell и C++, и основатель жаловался, как тяжело найти людей в команду. В Москву он прилетал в том числе искать хороших программистов.

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

    Все, что я слышал про Хаскель со стороны с тех пор, сводилось к одному — «с ним шутки плохи». Чтобы узнать хаскелистов получше, я пришел с расспросами к ним в телеграм-чат. Было довольно страшно, и как оказалось, не зря.

    О Хаскеле не стремятся говорить популярно, и на такие затеи, кажется, поглядывают с презрением. Уж если говорить — то с максимальной полнотой и объективностью. «Одно из характерных качеств Хаскеля как языка и сообщества в том, что они вместе не стремились стать популярными, дав простой ответ на популярные вопросы. Вместо этого выстраивали логичный principled путь решения реальных проблем, а не быстрого проникновения в сердце прохожего интересующегося» — написали мне там.

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

    Денис Мирзоев (nolane): В университете по предмету «Языки программирования» мне предложили пройти курс на Coursera по Хаскелю за один дополнительный балл из ста. Потом ещё был курс функционального программирования, на котором проходили Хаскель. Написал курсовую и выпускную работу бакалавра по GHC. Нашёл работу в качестве Хаскель-программиста.

    Было тяжело, и тяжело до сих пор. Когда начинаешь изучать Хаскель, приходится постигать очень много новых концепций. Это сложная работа. Буквально учишься программировать заново.

    Многим сейчас будет трудно вспомнить, как они начинали свой путь в программировании, как трудно было понять, что такое «указатель», что такое «функция», что такое «класс». Возможно поэтому изучение Хаскеля даётся так тяжело. С возрастом становится труднее усваивать новое.

    Doctor_Ryner: Однажды на испытательном сроке я завалился на Redux, поэтому, смотря уроки от его создателя, решил поближе с этим всем познакомится. Сначала применял изученные практики в JavaScript, но потом узнал о Haskell, который считается истинным функциональным языком. Меня сразу привлекла его элегантность и куча новых неизвестных мне концепций.

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

    Юрий Сыровецкий (cblp): Сложнее всего изучать Хаскель вторым, когда не прошёл синдром утёнка к первому языку.

    Чем хорош и чем плох язык?


    Doctor_Ryner: Язык очень краткий, элегантный и гибкий, не зря на нем половина библиотек — это EDSL (как минимум такое впечатление).

    Юрий Сыровецкий (cblp): Высокая выразительность, легко переносить предметную область в код, оптимальное сочетание императивной и функциональной парадигм. Легко строить абстракции над данными и алгоритмами, что позволяет думать о задаче, не отвлекаясь на несвязанные мелочи.

    Джон Доу: Строгая сильная (я бы сказал, фашистская) типизация.

    Игорь Шевнин (interphx): Очень выразительная система типов. Не настолько мощная, как у Idris или Agda, но достигает той золотой середины, когда выразить можно почти всё, и при этом вывод типов работает нормально. Не надо везде помечать их вручную.

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

    Doctor_Ryner: Изучая Haskell, ты скорее всего наткнешься на высказывание «if it compiles, it is probably correct». Тут нет null, сама функциональная парадигма очень строга и принуждает тебя следовать определенным правилам, которые в большинстве случаев ведут к лучшему дизайну.

    Например, в языке нет переменных — только константы. Тебе не приходится следить за тем, что и где ты присваиваешь. Haskell поощряет использование чистых функций, что ведет к отсутствию побочных эффектов. Функциональный дизайн просто заставляет программу работать как одно целое, в противовес ООП, где в мир выброшена куча объектов и объекты пытаются общаться друг с другом путем побочных эффектов, превращая приложение в непредсказуемое месиво. На работе достаточно страдаем от такого с C# в Unity.

    Денис Мирзоев: Встроенная ленивость повышает выразительность языка. Многие алгоритмы становятся проще. Она может увеличить производительность, если результаты промежуточных вычислений не будут использоваться. (К примеру `head. sort` работает за линейное время).

    Игорь Шевнин: Ленивая модель вычислений обычно помогает, но когда порядок вызова функций важен, может быть трудно разобраться, что происходит.

    Doctor_Ryner: Он компилируемый, что сразу же дает огромный прирост в скорости.

    Денис Мирзоев: По скорости сравним с Java, но не такой быстрый как C.

    Игорь Шевнин: Из коробки есть поддержка расширений, которые позволяют допилить язык и систему типов. При этом есть много широко используемых расширений, которые знакомы сообществу, имеют приличные примеры и документацию и не являются нишевыми.

    Doctor_Ryner: В стандартной библиотеке Prelude есть очень плохие функции наподобие read, head, readFile, которые могут выкинуть Exception и положить программу, вместо того, чтобы возвращать Maybe. Поэтому приходится использовать альтернативы или писать свои реализации.

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

    Денис Мирзоев: Не хватает тулов: нет полноценной IDE, очень мало средств для замеров производительности, нет отладки «по шагам» — это вообще говоря фундаментальная проблема.

    Для каких проектов Haskell подходит лучше всего?


    Юрий Сыровецкий: Для сложных задач, связанных с безопасностью или деньгами, где высока цена ошибки.

    Doctor_Ryner: Для всего, где нужно проводить вычисления, преобразование и анализ данных. Сильно удивлен, что Haskell менее популярен в Data Science, чем Python.

    Игорь Шевнин: Я бы не рискнул использовать его для встраиваемых систем (производительность неплоха, но всё же есть значительный оверхэд по потреблению памяти из-за ленивых вычислений) и мелких скриптов (там эта строгость просто не нужна). Также надо понимать, что найти разработчиков в команду намного сложнее, чем для мейнстримных языков.

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

    Игорь Шевнин: Но благодаря краткости и строгости Haskell подходит почти для любых задач.

    Начинать изучать разработку с Haskell — хорошая идея?


    Игорь Шевнин: Начинать — вряд ли, потому что подавляющее большинство кодовых баз, с которыми человеку придётся работать, написаны не на нём.

    Джон Доу: Плохая, плохая идея! Языки не из семейства ML — а такие из промышленных вообще все — потом будут для вас шоком.

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

    Doctor_Ryner: Всех новичков, которых я обучаю, я обязательно знакомлю с Haskell. Люди, которые не изучали императивные стиль, гораздо проще ориентируются в функциональном коде и быстрее учатся, потом даже если работают с объектно-ориентированными языками, они привносят хорошие архитектурные решения и функциональные практики.

    Юрий Сыровецкий: Начинать лучше сразу с нескольких принципиально разных языков, например, Си, Хаскель и Смолток, в любом порядке. Ни один язык в
    отдельности не даст полного понимания.

    Haskell — достаточно старый язык. Это хорошо или плохо?


    Юрий Сыровецкий: Развивается язык очень активно, груз совместимости только ради совместимости не тянет.

    Джон Доу: Стандарт принят в 1998-ом, но это не заметно: до сих пор новые версии компилятора, потенциально ломающие обратную совместимость, выходят примерно раз в полгода.

    Денис Мирзоев: Haskell не старый, а проверенный временем. В язык никогда не попадут непродуманные изменения. Так что это скорее хорошо.

    Про Haskell говорят, что это один самых сложных языков. Это так?


    Doctor_Ryner: Как сам язык — нет. Сложны скорее абстракции, которые в нем используются. Человек, который никогда не видел кода на Haskell, может просто сойти с ума от потока новой информации и разных непривычных конструкций.

    Масло в огонь подливает то, что язык накладывает кучу «ограничений», не позволяет или сильно затрудняет кучу вещей, которые не вписываются в функциональную концепцию.

    Джон Доу: Чтобы первый элементарный проект хотя бы просто скомпилировался, ушло почти два месяца курения учебников, мануалов и туториалов по вечерам. Правда скомпилировавшись, проект сразу заработал и фигачил под полной нагрузкой (6k rps с пиками до 15) полгода, без изменений вообще.

    Денис Мирзоев: Готов поспорить, что если школьник начнёт изучать программирование с Хаскеля и продвинется достаточно далеко, то императивное программирование ему покажется более сложным и менее интуитивным.

    Игорь Шевнин: Сложность относительна. Из мейнстримных языков я всё ещё считаю C++ самым сложным. Языки для доказательства теорем (Agda, Coq) будут посложнее Хаскелля в концептуальном смысле. Haskell — несложный язык, но его паттерны и библиотеки — стандартные и сторонние — выучить удастся далеко не сразу.

    Всегда ли его сложность оправдана?


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

    Doctor_Ryner: Зачастую сложные конструкции Haskell позволяют создавать очень короткие решения, которые еще и оказываются очень гибкими и модульными.

    Юрий Сыровецкий: Разве что управление эффектами бывает громоздко, хотя почти
    всегда это лучше, чем отсутствие управления. Но над его упрощением
    ведутся работы.

    Джон Доу: Язык для привыкших к обычным python/php/whatever вообще производит впечатление ортогонального к реальности. Для людей, которые изначально не интересовались теорией категорий, добиться результатов с абсолютного нуля — очень тяжело.

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

    Haskell видится языком как будто для математиков, а не для разработчиков. Как думаете, он не распространен широко из-за этого?


    Денис Мирзоев: Это демонстрация принципа, которому следуют главные разработчики Хаскеля — «avoid success at all costs». Смысл, конечно, не в том, что нужно избегать успеха, а в том, что нужно избегать успеха, цена которого слишком высока.

    Можно было сделать Хаскель популярным. Есть, к примеру, поддержка этого языка со стороны Microsoft. Можно было сделать язык более императивным, принимать какие-то быстрые и непродуманные решения, чтобы завоевать популярность. Можно было использовать много грязных приёмов, но благодаря такой правильной позиции главных разработчиков ничего подобного не было.

    Да, популярность языка не очень высока, но зато не страдает его качество. Мне очевидны преимущества Хаскеля по отношению к императивным языкам, большинство его проблем разрешимы, поэтому я уверен, что большая популярность ещё придёт по мере его развития.

    Юрий Сыровецкий: Таким он видится только людям, ничего про него не знающим. В
    «реальной» разработке Хаскель применяется давно, примеры легко найти в
    вашей любимой поисковой системе. В частности, мы в ЛК использованием
    Хаскеля довольны, и ничего другого на его месте не видим.

    Игорь Шевнин: Что такое «язык для математиков» я толком не знаю. Это либо R/MatLab/Mathematica для расчётов и статистики, либо Python, потому что он простой и требует меньше инженерного бэкграунда. Но не Haskell. Алгебраические понятия типа моноидов используются в нём из практических соображений, а не только для дополнительной строгости.

    Основную роль в популярности сыграла историческая распространённость C/C++/Java/C# в энтерпрайзе, они заняли нишу. Но сейчас многие компании начинают использовать Haskell и другие функциональные языки.

    С каким япом ты бы сравнил Haskell и в чью пользу?


    Джон Доу: Из более или менее распространенных — с Erlang. Но на Erlang все же проще писать и его проще выучить, как мне кажется.

    Денис Мирзоев: Я хорошо знаю C, С++, Java и Haskell. C++ даже сравнивать ни с чем не надо, язык ужасен. Си — хороший язык для низкоуровневой разработки. В этой нише он будет лучше. В остальном я бы предпочёл Haskell.

    Выбор между Java и Haskell уже труднее, но тут тоже нужно смотреть на конкретную задачу. Под андроид на Haskell будет скорее всего трудно писать, в этом случае лучше Java. А вот сервера писать на Haskell почти также удобно как и на Java. Если окружение позволяет — тулинг, доступность библиотек, — то я обычно выбираю Haskell.

    Doctor_Ryner: С C#, достаточно погуглить, как реализовать Maybe на C# и на Haskell. Очень странно, что диктаторский чисто функциональный Haskell чувствуется гораздо более гибким и свободным. На самом деле это две крайности.

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

    Игорь Шевнин: С Rust, пока что в пользу Rust. Он берёт очень многое от Haskell и других ФП-языков, но при этом дружит функциональный подход с императивным, а разработчики и сообщество намного грамотнее и более последовательно подошли к развитию языка с самого начала.

    Что думаете про сообщество хаскелистов?


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

    Doctor_Ryner: Haskell сообщества зачастую содержат в себе пугающе умных людей, которые всегда готовы помочь. Не зря ходят локальные мемы про PhD, теорию категорий и академиков. Если заходя в чат по другим языкам, ты видишь, что люди обсуждают обычные production-проблемы и структуры данных. В чате по Haskell перед тобой сразу выскакивают монады, лемма Йонеды, аппликативные функторы, написание безумных типов и прочее-прочее.

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

    Говорят, хаскелисты высокомерные. Правда?


    Денис Мирзоев: Да. Мне кажется высокомерность связана с тем, что они очень любят свой язык и расстроены его недооценённостью.

    Джон Доу: Нифига подобного.

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

    Игорь Шевнин: Высокомерие — слишком сильное слово. Тут скорее дело в том, что ФП, ООП, различие ООП-классов и union types, extension problem и много других понятий однажды складываются в очень чёткую картинку, и после этого становится трудно воспринимать людей, которые пытаются противопоставить ООП и ФП или другим образом представить широкую проблему в узкой перспективе.

    Почему ФП-языки до сих пор нишевые?


    Денис Мирзоев: Их преимуществ всё ещё не достаточно, чтобы заинтересовать большое количество программистов. Трудность в изучении не способствует популярности. Проблемы с тулингом тоже многих отпугивают, а мне кажется как раз увеличение численности сообщества могло бы решить эту проблему. Получается замкнутый круг.

    Игорь Шевнин: Нишевость постепенно проходит, а функциональные концепции подтягиваются в другие языки.

    Doctor_Ryner: Сами функциональные принципы и языки, что их поддерживают, уже повсеместны. Даже для шарпов есть Linq и некоторые другие библиотеки. Нишевые скорее чисто функциональные языки, так как в них используются нестандартные концепции.

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

    Похожие публикации

    Комментарии 122

      +9
      Жаль, что Haskell не был моим первым языком программирования. Очень интересно, какими разработчиками станут те школьники (студенты), которые начнут с Haskell и далее еще что-то функциональное, вроде Scala или F#.
        +2
        Ещё интересней будет посмотреть на результаты, если Haskell будет первым языком программирования для ребенка, родной язык которого — ифкуиль.
          +1
          Не выдержит несовершенство этого мира.
            +1
            Тогда уже лучше Ложбан пусть будет первым родным. Он всё-таки функциональный в каком-то смысле, и более простой, и носители есть. В случае с Ыфкуилем полный швах, нет у меня уверенности, что его кто-то знает.
          +6
          >>лет 20 назад железо было не достаточно производительным для функциональных языков

          ой, дайте мне это развидеть.
            0

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

              +5

              Ну да, ну да.


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

                +3
                а для него делали специальное железо

                ....
                  +6
                  Лисп — обычный императивный язык, там мало функциональщины и иммутабельности.
                    +1

                    Искренний вопрос: можете более детально объяснить, почему так?
                    Мне непонятно, потому что ещё в универе мне преподавали на нем ФП + я сходу не вижу почему он на считается функциональным.

                      +1
                      Лисп ненамного функциональней, чем JavaScript, например. В универах обычно преподают C, Pascal, примитивный С++ сначала, на них функциональное программирование выглядит громоздко и неуместно. По сравнению с ними лисп действительно вполне функционален. Если преподавать Python, JavaScript, тут уже каких-то преимуществ у лиспа не будет. Разве что списки лисповые и задачи на них позволяют хорошо въехать в иммутабельные списки, но в общем-то каркать и кдрать можно хоть на чём.
                        +2

                        JS стал перенимать функциональные штуки не так давно. Python, по моему опыту не слишком удобен в ФП. Да, в этих языках есть средства для ФП, как и во многих других, но я не понимаю как это делает Лисп не функциональным языком?

                          0
                          Конечно, он функциональный! Для некоторого определения «функционального».
                            +1
                            Соглашусь, что тут вопрос в определениях. Меня учили, что функциональный стиль программирования это когда функции передаются в качестве параметра. Передавать функции параметром в C формально можно, но писанины много и замыканий нет, замыкания придется делать самому через дополнительный контекстный параметр. Да и объявить функцию тут же аргументом нельзя, надо объявлять отдельно. В паскале то же самое. В том же лиспе это выглядит весьма естественно и в JS это всё было с самого начала. Не зря ходят байки, что JS это лисп с сишным синтаксисом. Если для вас ФП это иммутабельные структуры и вообще иммутабельность во все края, то да, JS тут не слишком хорош, хотя с современным синтаксисом можно что-то изобразить, но тут и традиционные лиспы не подойдут, там везде есть мутабельность.
                              0
                                0

                                Схема ж не лисп.

                                  0

                                  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.
                                    0
                                    Scheme — это lisp:

                                    "scheme же не лисп" — это такая шутка. Курица — не птица, scheme — не lisp.
                                    Дело в том, что группа scheme-derived лиспов семантически очень сильно отличается от группы "классических лиспов", кодификатором которых является на данный момент common lisp. Эти различия намного существеннее, чем, например, между сишкой и джавой.


                                    По-этому, когда вы говорите "чтото там лисп, но ведь scheme..." — это не особо корректно вне контекста конкретного языка. На практике нет смысла говорить о лиспах в общем.

                                +1
                                Передавать функции в качестве параметра — downwards funarg problem — это лишь малая часть функционального стиля.
                                0
                                Лисп — не один язык, а больщое симейство.
                                В Common Lisp стандартная библиотека рассчитана на мутабельность всего и вся, не требуется и часто не делается оптимизация хвостовых вызовов, очень сильно развиты конструкции циклов, для функций высщих порядков требуется специальные конструкции.
                                Scheme вполне функциональный. Мутабельность там изредка используется для оптимизации, но без нее удобно обходиться.
                                  +2
                                  Странно что никто Clojure не вспомнил/упомянул в качестве современного диалекта Лиспа, где иммутабельность из коробки, впрочем элемент «мутабельности» там тоже присутствует там где это необходимо. И Clojure вполне себе функциональный язык.
                                    0
                                    Да, это хороий пример функционального языка.
                              +2
                              Я не глубокий специалист в лиспе, надеюсь, кто-нибудь поправит. Знаю только, что есть много разных лиспов: изначальный Лисп МакКарти — совсем императивный, в Common Lisp есть элементы ФП, в Scheme их ещё больше.

                              Преподавали, наверно, потому что в нём есть базовые элементы ФП — лямбда-абстракция и замыкание, а также односвязный список в сердце языка. Но шаг в сторону — и появляются мутации. С комбинаторами не так удобно работать, как в языках с синтаксисом ISWYM (*ML, Haskell). С таким же успехом можно на Питоне и С++ преподавать ФП.

                              Так что Лиспы считаются функциональными, но примерно в той же степени, что и Питон.
                            +1
                            Попробуй без Data.Map реализовать tree на обычных языковых конструкциях haskell типа списков и кортежей хотя бы бинарное красно-черное дерево с ребалансировкой и прочими удовольствиями. Я после прочтения туториала долго плевался от скорости языка, когда в качестве самостоятельного задания делал компрессию с использованием huffman tree. Только гораздо позже плотно познакомился с IO()-монадой и понял ее мощь для работы внутри языка, а не только как средство для общения с внешним миром.

                            Я к тому, что структуры, внешне выглядящими иммутабельными, для внутренних алгоритмов необязательно должны быть иммутабельными.
                              +4
                              Я к тому, что структуры, внешне выглядящими иммутабельными, для внутренних алгоритмов необязательно должны быть иммутабельными.

                              Тогда лучше ST, а не IO.


                              А вообще, говорят, книжка Окасаки, Purely functional data structures, весьма хороша. Но я её ещё, увы, не читал.

                                0
                                Спасибо, посмотрю
                                  +1
                                  Книжка чудо как хороша. И красно-черные деревья там кажется есть.
                            +1
                            Стоит понимать что «недостаточно» не значит «невозможно», но излишняя нагрузка на память, иммутабельность и кол-во занимаемого дискового пространство вовсе не шли на пользу развития языка и стоит понимать что я имел ввиду именно чистые функциональные языки на производительность которых жалуются до сих пор, не говоря уже о конце 90-ых
                              +5
                              Действительно, ведь за 20 лет мы скорее научились существенно более эффективно компилировать функциональный код. ghc прям алмаз с точки зрения технологии компиляторостроения.

                              А иммутабельность вообще упрощает сборку мусора, например.
                                +3

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

                                  –2

                                  Однако в хаскеле очень много мутабельности: все ленивые вычисления реализованы через мутабельность (с точки зрения GC).


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

                                    +2

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

                                      0

                                      Во-первых, я сразу в скобочках уточнил: с точки зрения Garbage Collector. Я ведь отвечал на замечание, что "иммутабельность вообще упрощает сборку мусора".


                                      Во-вторых, я привел пример, доказывающий, что Хаскель не истинно immutable, т.к. в понастоящему immutable языке нет возможности организовать двухсвязный список, да и вообще любую структуру с циклами.


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

                                        0
                                        Такие двусвязные списки в хаскелле всё равно будут иммутабельные. Ими можно эффективно пользоваться только read-only. Чтобы внести изменение в эту структуру, придется ее полностью перестроить и создать новый список.
                                      0
                                      Не совсем правда. Ленивое значение — это как бы «переменная», в которую можно присвоить не больше одного раза. Разве это мутабельноность?
                                        0

                                        С точки зрения Garbage Collector — да. GC и не подозревает о том, что вы (как программист) не замечаете этой мутабельности.

                                          +1
                                          Программисту не очень интересно, что себе думает GC. С точки зрения процессора вообще нет ни GC, ни переменных, ни функций, — только одно мутабельное пространство памяти.

                                          Мы же рассуждаем о мутабельности с точки зрения программиста и семантики языка.

                                          Да и точки зрения зрения GC «мутабельная ровно 1 раз» переменная от настоящей мутабельной отличается существенно, о чём было высказывание выше.
                                            0

                                            Я отвечал на замечание "иммутабельность вообще упрощает сборку мусора".


                                            И, смотрите мой ответ https://m.habr.com/ru/post/438970/comments/?reply_to=19737594#comment_19737792

                                              0
                                              Я тоже именно об этом. Иммутабельность вообще упрощает сборку мусора. Даже хаскельная, которую вы считаете ненастоящией.
                                                0

                                                И если вы почитаете про Garbage Collector в GHC, аы узнаете, что даже "мутабельная ровно 1 раз" переменная сильно усложняет ему жизнь.

                                                  0
                                                  Да, но и упрощает по сравнению с IORef
                                    +11
                                    Могу рассказать о себе.
                                    Когда я заинтересовался функциональным программированием (где-то в районе 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 имеет смысл учить как первый язык.
                                      +2
                                      Правда, из-за ленивости, на больши интервалах начиналась утечка памяти, с которой было тяжело бороться (хотя для моделей проблема не критичная).

                                      А, кстати, чего там? Если соответствующий путь в алгоритме можно воспроизвести на достаточно маленьких данных, то сборка со всякими -prof -fprof-* (ну или stack build --profile, мы ж в 2019), и потом +RTS -h или -hr (hr вот вообще крутота для такого, меня выручал).

                                        0
                                        Я не особо заморачивался по этому поводу. Один раз память начала расти после отключения печати логов, я просто выкинул генерацию списка с логами. В других до сути не добрался. Сергей Зефиров как-то научился с этим бороться.
                                      +4
                                      Еще о практичности Haskell — в Лаборатории Касперского его используют для кодогенерации в встраевоемой ОС (с помощью библиотеки Ivory). То есть он даже в embedded полезен, особенно с учетем стоимости ошибок.
                                        –2
                                        Игорь Шевнин: Ленивая модель вычислений обычно помогает, но когда порядок вызова функций важен, может быть трудно разобраться, что происходит.

                                        Когда порядок функций важен (например когда надо приготовить файл или написать в базу), вы должны въявную это указывать при помощи IO/do, что как бы и есть императивное программирование. Другое дело, что ваш Хаскель таки на ура разрешает сайд-эффекты, а далеко не каждый разработчик сможет их увидеть. И в один прекрасный момент вместо (INSERT-UPDATE) выполняется (UPDATE-INSERT), вызывая очередную головную боль.


                                        Игорь Шевнин: Но благодаря краткости и строгости Haskell подходит почти для любых задач.
                                        Doctor_Ryner: Зачастую сложные конструкции Haskell позволяют создавать очень короткие решения, которые еще и оказываются очень гибкими и модульными.

                                        Короткие не значит понятные. Был такой write-only язык Perl, там тоже были короткие однострочники, в которых сам автор уже через неделю нифига не шарил.


                                        в противовес ООП, где в мир выброшена куча объектов и объекты пытаются общаться друг с другом путем побочных эффектов, превращая приложение в непредсказуемое месиво.

                                        В ООП мире моделируется система сущностей, наиболее приближенная к реальному миру, а также ее эволюция во времени. В ФП моделируются абстрактные преобразования над исходными данными. Но тем не менее на определенном этапе любое ФП всегда скатывается в императивное программирование, например, когда нужно осуществить системные вызовы в определенной последовательности, и именно здесь начинаются настоящие сайд-эффекты. Без этого никак.


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

                                        В том-то и дело. С одной стороны, мы хотим дать исчерпывающее описание предметной области на этапе декларации, чтобы компилятор отловил как можно больше и т.д. С другой стороны, а так ли это необходимо, и стоит ли платить за это ценой простоты и понятности кода, когда проще поставить в коде пару assert-ов или ручных приведений типов? Если учесть, что большинство сегодня вообще пишет без типов (JS, Python) и как-то худо-бедно справляется. Когда вы объясните клиенту, как моноиды и полугруппы связаны с его прибылью, тогда и поговорим за мощную систему типов.


                                        Под андроид на Haskell будет скорее всего трудно писать, в этом случае лучше Java. А вот сервера писать на Haskell почти также удобно как и на Java.

                                        Уже смущает слово "почти". Как только прикрутите к серверу базу данных, так у вас появится мутабельный стейт, и вся девственная чистота функций будет варварски сломана. Поэтому код потребует императивного последовательного применения изменений стейта, что не сильно будет отличаться от кода на Java + фреймворк.


                                        Масло в огонь подливает то, что язык накладывает кучу «ограничений», не позволяет или сильно затрудняет кучу вещей, которые не вписываются в функциональную концепцию.

                                        Ну да, это как всегда задачи виноваты, что не подходят под такой прекрасный язык.


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

                                        Прям мытарства какие-то с религиозным оттенком. На Ноде, РубиРейлсе или Спрингбуте через 5 минут уже все запустится, и работать будет не хуже. С таким же успехом можно программировать на брейнфаке и гордиться этим. Концептуальненько! Любой же нуб хочет сразу видеть что-то работающее, а уже потом разбираться с этим. На два месяца терпения ни у никого не хватит.


                                        Денис Мирзоев: Да. Мне кажется высокомерность связана с тем, что они очень любят свой язык и расстроены его недооценённостью.

                                        Высокомерность говорит о том, что в большинстве случаев ЧСВ — это единственная мотивация почему эти люди изучили Хаскель. Компенсируют что-то.


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

                                          +4

                                          Хаскель не меняет местами эффекты, так что


                                          И в один прекрасный момент вместо (INSERT-UPDATE) выполняется (UPDATE-INSERT), вызывая очередную головную боль.

                                          это невозможно.

                                            +1
                                            Короткие не значит понятные.

                                            Да, но с коротким текстом проще добиться понятности, чем с длинным.

                                              0
                                              Да, но с коротким текстом проще добиться понятности, чем с длинным.

                                              Это не так. Можете взять какой-нибудь текст и удалить пробелы, знаки препинания, окончания слов — понятнее не станет.

                                                +1
                                                Если добавить пробелы или буквы, тоже понятнее не станет. И что?

                                                Нет, это в обратную сторону работает. Если текст понятный, то он будет скорее короткий, чем длинный (при равном количестве информации).
                                                  +1
                                                  Ну вот, например, оператор «сиськи»:
                                                  (.).(.)

                                                  Без :t мне было сложно определить, что это тоже самое, что и инфиксный оператор «точка»:
                                                  .
                                                  , но только для функций с двумя аргументами. По мне так, когда в коде встретишь, сразу и не поймешь значение иероглифа, если ранее не встречал такую конструкцию.
                                                    0
                                                    Если добавить пробелы или буквы, тоже понятнее не станет.

                                                    Ну и что?


                                                    Если текст понятный, то он будет скорее короткий, чем длинный (при равном количестве информации).

                                                    Выше я привел контрпример, который показывает, что это не так.


                                                    (при равном количестве информации)

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


                                                    Если текст понятный, то он будет скорее короткий, чем длинный (но только в том случае, который недостижим на практике).
                                                      +1
                                                        +1
                                                        Текст почти всегда раздувается ненамеренно.
                                                          0
                                                          Текст почти всегда раздувается ненамеренно.

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


                                                          glvrd.ru

                                                          Очень плохо работает. Вставил две строчки из предыдущего поста — и все 4 указания из 4 были ошибочными.

                                                    0
                                                    иногда с point-free нотацией можно такую скороговорку написать, что без «100 грамм» не разберешь, особенно в этом плане выдаются APL-подобные языки вроде J.
                                                      +1
                                                      Да, но в языках со статической типизацией типы подвыражений очень хорошо помогают в таком коде разбираться.
                                                    +2
                                                    и именно здесь начинаются настоящие сайд-эффекты. Без этого никак.

                                                    Правильно, поэтому полезнее оказывается язык, в котором сайд-эффектами можно управлять.

                                                      +2
                                                      Собственно для этого монады и придуманы.
                                                        +1
                                                        И не только монады.
                                                      +1
                                                      Когда вы объясните клиенту, как моноиды и полугруппы связаны с его прибылью, тогда и поговорим за мощную систему типов.

                                                      Своему клиенту мы объяснили. Вы хотите, чтобы мы объяснили вашему клиенту? Вы сами не в состоянии?

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

                                                        Сами себе противоречите.

                                                          0
                                                          через 5 минут уже все запустится

                                                          На Хаскеле меньше 5 минут. Или вы экстраполировали ошибку одного человека на всю технологию?

                                                            +6
                                                            В ООП мире моделируется система сущностей, наиболее приближенная к реальному миру

                                                            Это может быть и заблуждение. Как я уже писал, у кого-то из мэтров программирования я встречал мнение, что на самом деле ООП исключительно плохо натягивается на реальный мир. А, ну и чтоб два раза не вставать — «С наследованием оно не натягивается вообще никак (потому что ко/контравариантность) без адовых костылей.» (С) 0xd34df00d
                                                            На Ноде,

                                                            Пишите на Ноде, в чем проблема-то? Вас страшные Хаскелисты тащат крючьями к себе, тряся монадами?
                                                            В конце-концов, каждый мочит как он хочет.

                                                            Вот эта фраза лишает смысла весь ваш комментарий.
                                                              +5
                                                              Другое дело, что ваш Хаскель таки на ура разрешает сайд-эффекты, а далеко не каждый разработчик сможет их увидеть. И в один прекрасный момент вместо (INSERT-UPDATE) выполняется (UPDATE-INSERT), вызывая очередную головную боль.

                                                              В IO? Ну да, ещё бы не разрешал.


                                                              Хотите гарантировать порядок INSERT/UPDATE уже внутри do — вам в идрис (ну или в свободные монады + GADT + синглтоны). Что, кстати, довольно иронично перекликается с вашим тезисом о нужности типов позже.


                                                              Короткие не значит понятные.

                                                              Это в основном к типам относится. Ну да, есть даже такое высказывание:
                                                              «Java's architecture astronauts are well known. Dependently typed languages enable something much worse: type astronauts. A function cannot merely be written that works on some concrete type. It needs to be abstracted and abstracted until it operates on elements of some obscure algebraic structure mentioned once, in passing, in a PhD thesis in 1983.»


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

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


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

                                                              Я просто делаю за три месяца то, что соседняя команда обещала сделать за 9, и у меня всё готово, работает и устойчиво к изменяющимся требованиям (потому что ничего не отваливается в рантайме из-за изменений).


                                                              Как только прикрутите к серверу базу данных, так у вас появится мутабельный стейт, и вся девственная чистота функций будет варварски сломана. Поэтому код потребует императивного последовательного применения изменений стейта, что не сильно будет отличаться от кода на Java + фреймворк.

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


                                                              И сравнивать это с джавой — ну такое.

                                                                0
                                                                >И сравнивать это с джавой — ну такое.
                                                                Ну, сравнивать-то можно, очего же нет? Я правда вам скажу, что хорошие проекты на Java делаются примерно так же — путем выделения максимально чистой значимой части, убирания стейта, ну то есть примерно теми же средствами, только инструмент при этом не особо помогает.
                                                                  0
                                                                  Что не так с порядком действий в Хаскельной do?
                                                                    0

                                                                    Система типов не умеет читать мысли и не запретит вам сделать


                                                                    do
                                                                      updateRecord (\Record { .. } -> ident == 1) (\r -> r { name = "foo" })
                                                                      insertRecord Record { ident = 1, name = "meh" }

                                                                    и потом удивляться, почему у вас в базе Record { ident = 1, name = "meh" } вместо Record { ident = 1, name = "foo" }.

                                                                      0
                                                                      Почему это должно быть запрещено? Может, автор хочет именно то, что здесь написано — сначала update, потом insert?
                                                                        0
                                                                        Не знаю, почему, но я не могу придумать другую интерпретацию претензии из исходного коммента. Может, Throwable нас рассудит.
                                                                          +3
                                                                          Вероятно, автор исходной претензии что-то читал про негарантированный порядок вычислений и не знает, чем вычисление отличается от действия.
                                                                            0

                                                                            Т.н. "вычисление" не может достать что-то из БД или не может вызвать системную функцию? И функции внутри функциональной композиции не могут иметь "действия"?
                                                                            Да, я имел ввиду именно негарантированный и вообще неявный порядок вычисления, когда вы делаете сложную композицию из функций, которые внутри содержат некие действия с общим стейтом. И я так думаю, это именно те случаи, которые имел ввиду Игорь Шевнин в своей фразе.

                                                                              +1
                                                                              Т.н. "вычисление" не может достать что-то из БД или не может вызвать системную функцию?

                                                                              Не может (без unsafe).


                                                                              И функции внутри функциональной композиции не могут иметь "действия"?

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


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


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

                                                                              Вот это как раз невозможно (возможно только если специально стрелять себе в ногу через unsafe). Неявное изменение порядка вычислений есть, но оно не вредит, а либо не имеет значения, либо помогает.


                                                                              И я так думаю, это именно те случаи, которые имел ввиду Игорь Шевнин в своей фразе.

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

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

                                                                                Конечно, можно обмануть тайпчекер и замаскировать нечистую функцию как чистую, тогда действительно порядок вызовов может произвольно поменяться. Но это уже разработчик виноват будет, такое везде можно сделать.
                                                                    +1
                                                                    Основной смысл в разделении эффектов и возможность выразить пусть и императивную предметную область максимально типобезопасно.

                                                                    Я очень даже за типы и ненавижу безтиповые языки. Однако ни одна из современных областей знаний, кроме математики, на сегодня не оперирует терминами теории категорий и гомотопической теории типов. Поэтому если внезапно удастся создать Теорию Всего (и описать ее на Хаскеле), скорей всего она так и останется теорией, ибо пользоваться ей будет бесконечно сложно.
                                                                    Между прочим сам алгоритм на императивном даже безтиповом языке программирования — это тоже вариант описания предметной области. И далеко не факт, что описание при помощи системы типов будет проще и понятнее самой императивной программы. Как указал один из респондентов, система типов может быть бойлерплейтом.


                                                                    Я просто делаю за три месяца то, что соседняя команда обещала сделать за 9, и у меня всё готово

                                                                    Ну вот это нифига не показатель. Показателем будет, например, когда весь стек компании (или большое число разнотипных задач) переписали на Хаскель, и стоимость проекта/сроки сдачи уменьшились на столько-то.


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

                                                                    Все данные в STM не запихаешь, а чтобы база стала STM, нужен как минимум serializable уровень изоляции. Кроме того, чтобы обеспечить чистоту, вам придется отделить все чтения от всех записей, а такая компоновка не всегда соответствует задаче — все-таки в каждом из бизнес-модулей выполняются сразу как чтения, так и записи.

                                                                      +2
                                                                      Однако ни одна из современных областей знаний, кроме математики, на сегодня не оперирует терминами теории категорий и гомотопической теории типов. Поэтому если внезапно удастся создать Теорию Всего (и описать ее на Хаскеле), скорей всего она так и останется теорией, ибо пользоваться ей будет бесконечно сложно.

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


                                                                      Ну вот это нифига не показатель. Показателем будет, например, когда весь стек компании (или большое число разнотипных задач) переписали на Хаскель, и стоимость проекта/сроки сдачи уменьшились на столько-то.

                                                                      Не понял, почему?


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

                                                                      STM — это один из способов доступа к самой базе, а не к данным внутри базы. Доступом к данным внутри базы заведует сама база, и это уже её внутренняя кухня.


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

                                                                      Зачем отделять? Почему в одной транзакции не может быть произвольного набора действий?

                                                                        0
                                                                        А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.

                                                                        Как правило в этом случае задача стоит достаточно конкретно и для ее решения хватает системы типов, предоставляемой типичным ООП-языком. Делал я как-то движок для покера, и подумал, что как раз тут пригодилась бы система типов для вычисления комбинаций. Оказывается, есть реализация на Хаскеле. Принцип более-менее понятен. Однако не могу сказать, что представленная модель сильно напоминает человеческое описание правил игры, а также, что сходный функционал на Java сильно в чем-то уступает.


                                                                        Не понял, почему?

                                                                        Может это вы оказались хорошим специалистов на фоне остальных, может задача была специфическая и ее эффективнее было решать на Хаскеле, может еще куча причин было. Я не слышал success stories от массового применения Хаскеля в компаниях, почему бы, если он настолько удешевляет разработку?


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

                                                                        Для примера возьмем абстрактный регистр X и какие-нибудь два вычисления, изменяющие его значения: X := f1(X) и X := f2(X). Не важно какая реализация у X — STM, файл или строка в базе данных. Есть всего два варианта реализации транзакции:


                                                                        1. Все чтения X будут выдавать одно и то же значение, которое было на момент начала транзакции, а все изменения X будут видны уже после транзакции.
                                                                        2. Все последовательные изменения X будут видны в той же транзакции.

                                                                        И оба способа плохие. В первом случае мы сразу получаем проблему "lost update". Во втором случае логика полагается на последовательное применение операций. Но поскольку в нашей функциональной программе последовательность чтений и записей не определена (или определена неявно), то это будет вести к трудноотловимым ошибкам.

                                                                          +1
                                                                          Второй вариант хороший. STM его обеспечивает. Поскольку чтение и запись регистра — императивный эффект, Хаскель обеспечивает порядок. Очень плохо, что в вашем языке последовательность чтений из записей не определена. Переходите на Хаскель.
                                                                            +2
                                                                            Как правило в этом случае задача стоит достаточно конкретно и для ее решения хватает системы типов, предоставляемой типичным ООП-языком.

                                                                            Не хватает, картинка.про.паттерны.пнг.


                                                                            У вас мультиметоды искаропки в языке? Кто наследуется от кого, квадрат от прямоугольника или прямоугольник от квадрата, вы уже решили? Tagless final вот прям так с пол-пинка строится? Система типов обеспечивает вам гарантию отсутствия нежелательных эффектов в STM-транзакции или в чистой функции? Как там с многопоточностью, опять же?


                                                                            И это я просто за 10 секунд нагенерил.


                                                                            Оказывается, есть реализация на Хаскеле.
                                                                            poker-eval: Binding to libpoker-eval

                                                                            Ну вы поняли :]


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

                                                                            С учётом вышесказанного — неудивительно.


                                                                            Может это вы оказались хорошим специалистов на фоне остальных

                                                                            Так, может, я оказался потому, что пользовался правильным инструментом?


                                                                            Я не слышал success stories от массового применения Хаскеля в компаниях, почему бы, если он настолько удешевляет разработку?

                                                                            Потому что хаскелистов мало :(


                                                                            Для примера возьмем абстрактный регистр X и какие-нибудь два вычисления, изменяющие его значения: X := f1(X) и X := f2(X).

                                                                            Ну так никто не мешает их вот прям так вот вызвать подряд в одной STM-транзакции и получить второй вариант.

                                                                            –1
                                                                            А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.

                                                                            Им присуща как раз динамическая типизация :)
                                                                            То есть тип яблок как объекта, в рантайме, но не тип терма.


                                                                            Tagless final

                                                                            Кривой костыль для языков, в которые нормальных макросов не завезли ;)

                                                                        +1
                                                                        > В ООП мире моделируется система сущностей, наиболее приближенная к реальному миру
                                                                        1. Несовершенный мир
                                                                        2. Идеализированная математическая модель
                                                                        Хм… логичный выбор. Проблема в том, что эти «сущности» помещены не в реальный мир, а в никуда и просто взаимодействуют между собой побочными эффектами мутируя все подряд, моделируя приближённый к миру хаос и непредсказуемость. Насчет JS, зачем у вас там в React то иммутабельность привносят? А TypeScript и Flow? От хорошей жизни? Нормально они без типов живут (в Python вообще типы добавили), ага, достаточно спросить в чате какого это поддерживать JS приложение без типов и тестов… с тестами для тестов, вот это то конечно лучше.

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

                                                                          Сущности — это лишь компоновка общего стейта, которая может отличаться для различных парадигм. Не важно чем он представлен — записями, объектами, переменными, таблицами в базе. Весь стейт мутирует всегда предсказуемо при последовательном применении операций, что отвечает интуитивной концепции времени. В каждый момент у нас есть стабильный snapshot всей нашей вселенной. Когда речь заходит о паралельном программировании, и нарушается sequential consistency, то все-равно так или иначе всю задачу стремятся свести к последовательному выполнению, изолируя области данных (например стек) и используя уже избитые примитивы синхронизации.
                                                                          Да, ООП далеко не самая лучшая парадигма, и большинство фреймворков предлагает обычное процедурное программирование даже в ООП-языках, разделяя stateful и stateless объекты.


                                                                          Всякие вещи на подобии взаимодействия с базами данных отделяются и отчищаются, смысл в том, что бы контролировать побочные эффекты, хаскель поощряет использование чистых функций

                                                                          Как я уже писал выше, это предполагает определенную компоновку бизнес логики: т.е. мы отделяем все чистое и вычислимое от всего грязного и "эффектного". Хорошо, если у нас более-менее однородная задача, и она вся легко перекомпонуется — все эффекты, например, можно свалить вконец операции. Но это не всегда подходит для сложных бизнес-задач, которые состоят из множества других атомарных модулей, каждый из которых содержит как вычисление, так и действие.

                                                                        –1
                                                                        del
                                                                          0
                                                                          Она может увеличить производительность, если результаты промежуточных вычислений не будут использоваться. (К примеру head. sort работает за линейное время).

                                                                          А это сам sort за квадрат тогда работает, что ли?

                                                                            0

                                                                            Зачем? Это просто вырождается в partial sort за счёт ленивости.

                                                                              +1
                                                                              Зачем? Это просто вырождается в partial sort за счёт ленивости.

                                                                              Очевидно, это верно не для любого алгоритма. Например, если это квиксорт, то чтобы взять от него head — надо, с-но, выполнить весь квиксорт, целиком


                                                                              Вот я попытался вспомнить какую-нибудь неквадратичную сортировку, которая в ленивом случае бы выродилась в линейный head, и не смог. Потому и вопрос.

                                                                                +4
                                                                                Очевидно, это верно не для любого алгоритма.

                                                                                Да, но на практике конкретно для sort верно (и при этом sort — O(n logn)).


                                                                                Я, кстати, так прикольно обжёгся как-то несколько лет назад, когда для курсеровского курса по биоинформатике запрогал Барроуза-Уиллера, и для теста сделал take 10 вместо вывода всего результирующего списка, и работало у меня оно адски быстро. Пришёл в один чатик по C++, похвастался, а потом до меня дошло, что сортировал я в итоге только первые 10 элементов.


                                                                                Например, если это квиксорт, то чтобы взять от него head — надо, с-но, выполнить весь квиксорт, целиком

                                                                                Совсем неочевидно. Пусть у нас (да, не совсем квиксорт, но пофиг)


                                                                                quicksort [] = []
                                                                                quicksort (x:xs) = small ++ large
                                                                                  where small = quicksort [y | y <- xs, y <= x]
                                                                                        large = quicksort $ x : [y | y <- xs, y > x]

                                                                                Чтобы взять первый элемент, мне нужно амортизированно взять только первый элемент small, вычислять large мне не нужно совсем. А далее рекурсивно.

                                                                                  +1
                                                                                  Прошу прощения, я не хаскелист, но разве оно не зациклится в последней строчке, если список начинается с минимального элемента?
                                                                                    0

                                                                                    Да, вы правы, конечно (и на самом деле оно там зациклится вообще всегда).

                                                                                      0

                                                                                      Ну допустил человек в попыхах ошибку. Но её легко исправить.


                                                                                      Правда, это в очередной раз доказывает, что ни один язык не может спасти от всех ошибок.

                                                                                    0
                                                                                    Во стандартной библиотеке Хаскеля сортировка пирамидальная.
                                                                                +7
                                                                                У меня такой опыт с Haskell: изучал, писал проги и библиотеки, и ничто не предвещало беды. Но в один прекрасный момент сложилась ситуация, что некоторый код вместо того, чтобы работать быстро, предпочитает работать медленно. Было ясно, что проблема не принципиальная, что просто имеет место быть глупый косяк, идиотизм в коде, создающий узкое место. Попытки профилирования никакой полезной информации не дали, и вообще все попытки что-нибудь с этим сделать никакой полезной информации не дали. Хотя нет, дали: я понял, что Haskell действительно не для всех, и я переоценил свои способности.

                                                                                Теперь я переписываю всё с Haskell'а на Rust. Многое уже переписал, всё летает (с тем же алгоритмом и без какой-либо оптимизации).

                                                                                Обращаясь ко всем, хочу сказать следующее. Люди! Haskell — это прекрасно! Учить его полезно любому! Но если вы, как я, поймёте, что не осилили, — не расстраивайтесь: Haskell правда сложный и правда не для всех; я проверил.
                                                                                  –10
                                                                                  C++ даже сравнивать ни с чем не надо, язык ужасен. Си — хороший язык для низкоуровневой разработки.

                                                                                  Всё ясно с этими товарищами. После этой фразы интерес к мнению этого человека упал до нуля.
                                                                                    0
                                                                                    Джон Доу: Строгая сильная (я бы сказал, фашистская) типизация.

                                                                                    На сколько я знаю, он же православный!
                                                                                      0
                                                                                      Лично мне, после знакомства с ООП откровенно «сломать голову» пришлось при ознакомлении именно с Prolog (declarative) нежели чем с Haskel или Lisp (functional). Я считаю, что нужно просто сначала понять парадигму, а потом начинать учить язык.
                                                                                      Всегда удивлял спор о том, что ООП лучше ФП и т.п., так как любой иструмент удобен там, куда он предназначен. Жарить в кастрюле тоже возможно, но не всегда оправдано :)
                                                                                        +2
                                                                                        После того как Ares_ekb опубликовал свою статью про теорию категорий, я потерял покой и сон и нашёл Голдблатта «Топосы. Категорный анализ логики». Это не книга, нет. Это борьба и торжество духа.
                                                                                        А после прочтения коллегой книги по Haskell стало понятно — язык очень хорош для качественного скачка компетентности программиста. Он даёт особый взляд, особое видение и на саму проблему, и на множество её решений. И даже если ни одно решение не получится сделать на ФП (а в мире JS, Go и PHP это часто бывает...), вы ничего не потеряете, но приобретёте многое. За которое в будущем вас будут уважать, платить заработную плату и приглашать на конференции. Не знаю, как это влияет на чсв, а вот на настроение влияет положительно )))
                                                                                          0
                                                                                          я потерял покой и сон и нашёл Голдблатта «Топосы. Категорный анализ логики»

                                                                                          Для начинающих — плохая книга, автор достаточно безалаберно относится к строгости изложения.

                                                                                            0
                                                                                            Мне пока не с чем сравнить. Если есть хорошие (для начинающих) по теории категорий — делитесь, пожалуйста.
                                                                                              0

                                                                                              "категории для работающего математика" Маклейна, тут без вариантов. В принципе, достаточно первых 5 глав (с решением задачек, конечно).
                                                                                              А Голдблатт — он интересный, но желательно его читать, уже имея хорошее представление о предмете.

                                                                                                0
                                                                                                Мне от неё припекает, там всё время отсылки к другим областям математики типа топологии, в которых я не очень шарю, и от которых я всё время чувствовал себя дном.
                                                                                                  0
                                                                                                  Мне от неё припекает, там всё время отсылки к другим областям математики типа топологии, в которых я не очень шарю, и от которых я всё время чувствовал себя дном.

                                                                                                  Ну теоркат без отсылок смысла не имеет, он же сам по себе бессодержателен. Да и отсылки там не требуют более чем базовых знаний.

                                                                                                0

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


                                                                                                Ещё вот — Написал учебник теории категорий

                                                                                                  0
                                                                                                  Вы — автор?
                                                                                                  Заключительная мысль: теория категорий не является древним знанием, смысл которого утрачен – это живая и тёплая наука.
                                                                                                  — хорошая мысль. И учебник интересный, берём на вооружение.
                                                                                                    0
                                                                                                    Вы — автор?

                                                                                                    Нет, я просто завсегдатай и активный участник dxdy.ru.

                                                                                                  0
                                                                                                  я тоже в ФП начинающий, читаю вот эту книгу: Category Theory for Programmers
                                                                                                  Объяснения понятные, примеры разбираются на Хаскеле и С++
                                                                                                    0
                                                                                                    Неретин Ю. А. "Категории симметрий и бесконечномерные группы".
                                                                                                    краткое описание
                                                                                                    Книга содержит систематическое изложение теории бесконечномерных групп, их представлений, а также полугрупповых и категорных оболочек. Подробно рассматриваются группа диффеоморфизмов окружности, бесконечномерные аналоги классических групп, группы преобразований пространств с мерой и некоторые группы токов. Обсуждаются также бесконечные аналоги симметрических групп и группы петель. Ряд разделов книги посвящен связанным с конечномерными группами Ли явлениям, которые стали известны лишь благодаря появлению теории бесконечномерных групп. Изложение основано на категорной версии метода вторичного квантования. Для математиков и математических физиков, так или иначе имеющих дело с бесконечномерными группами, а также студентов и аспирантов соответствующих специальностей.

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

                                                                                                      А что в случае такого подхода происходит, когда совокупность объектов/морфизмов не является множеством?

                                                                                                +2
                                                                                                Народ, заранее прошу прощения за возможно ламерский вопрос, но никто не подскажет хорошей IDE под хаскель? Чего-то подвигла меня эта статья на его изучение. Давно уже хотелось, но как-то было не до того. А сейчас почувствовал что пора, хотя в настоящее время сильно занят. Да и внука-оболтуса пора к делу припахивать. Не с С++ же с ним начинать!
                                                                                                  +1
                                                                                                  Я знаю два варианта:
                                                                                                  1. Плагины к эклипсу.
                                                                                                  2. leksah

                                                                                                  Оба рабочие, но оба не то чтобы слишком юзерфрендли. Я остановился на последнем, но по сравнению с IDE для Java это зачастую боль и страдание.

                                                                                                  PS: если вы пользуетесь emacs, то для вас есть еще варианты, но я их в живую не видел.
                                                                                                    +1
                                                                                                    А чего такого хорошего в плагинах эклипса? Насчет leksah, то у меня с ним был не очень хороший опыт, он мягко говоря очень сырой, я юзаю VS Code, с ним и ghcid даже автодополнение с подсветкой ошибок и варнингов в Reflex позволяет без проблем заставить работать
                                                                                                      0
                                                                                                      О, а покажите пжлст .cabal-файл этого проекта на Reflex (в котором ghcid работает).
                                                                                                        +1
                                                                                                        Там ничего делать не надо, все что нужно это создать проект на основе reflex-platform, далее запустить ghc shell в nix и из него запустить VS Code, и вот в нем уже ctrl + shift + P и Start GHCID (надо сперва плагин поставить)
                                                                                                    +1

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

                                                                                                      0
                                                                                                      В нашем большом сообществе ruHaskell есть вики для ответов на такие часто задаваемые вопросы github.com/ruHaskell/ruhaskell/wiki
                                                                                                      +1
                                                                                                      Есть плагины для IntelliJ IDEA, Visual Studio Code, Sublime, Atom, Vim, Emacs. Тут уж на ваш вкус.
                                                                                                        +1
                                                                                                        Можно взять просто лучшую в мире (кроссплатформенную) IDE Jetbrains IDEA и поставить в неё plugins.jetbrains.com/plugin/8258-intellij-haskell
                                                                                                        0
                                                                                                        Скажите, а как сочетается
                                                                                                        Не стоит забывать, что еще лет 20 назад железо было не достаточно производительным для функциональных языков, так что в мейнстрим функциональщина начала входить в последние годы, а интерес к Haskell только растет.

                                                                                                        и
                                                                                                        Денис Мирзоев: По скорости сравним с Java, но не такой быстрый как C.

                                                                                                        То есть для Java двадцать лет назад производительности хватало, а для Хаскеля было мало?
                                                                                                        Тут правда еще вопрос к 20 годам, потому что разница в производительности например Pentium II выпущенного 21 год назад и Pentium 4 (Northwood) — 17 лет назад была колоссальной
                                                                                                          +1

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

                                                                                                          0
                                                                                                          пройти курс на Coursera по Хаскелю

                                                                                                          Какой курс имеется ввиду?
                                                                                                            +1

                                                                                                            Соврал. Не на курсере проходил. Курс тут.

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

                                                                                                          Самое читаемое