Pull to refresh

Comments 133

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

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

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

Ну да, ну да.


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

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

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

UFO just landed and posted this here

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

Конечно, он функциональный! Для некоторого определения «функционального».
UFO just landed and posted this here

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

Scheme — это lisp:

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


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

UFO just landed and posted this here

Ну если говорить конкретно о CL vs r6rs, то общего у них скобочки и динамическая типизация, все остальное разное. CL работает внутри образа, это lisp-2 (разные пр-ва имен для ф-й и переменных), там есть свое ооп (CLOS), у них разная макросистема, стандарт CL не требует ТСО, с-но там есть примитивы для циклов, в отличии от схемы, где есть ТСО и циклы делаются через рекурсию. Вообще набор примитивов очень разный. Идеологически они очень разные — scheme более "академичный", достаточно минималистичный, мутабельные примитивы есть но их использование не приветствуется. С точки зрения общелисперов программирование на схеме — это bondage and discipline :)

Передавать функции в качестве параметра — downwards funarg problem — это лишь малая часть функционального стиля.
Лисп — не один язык, а больщое симейство.
В Common Lisp стандартная библиотека рассчитана на мутабельность всего и вся, не требуется и часто не делается оптимизация хвостовых вызовов, очень сильно развиты конструкции циклов, для функций высщих порядков требуется специальные конструкции.
Scheme вполне функциональный. Мутабельность там изредка используется для оптимизации, но без нее удобно обходиться.
Странно что никто Clojure не вспомнил/упомянул в качестве современного диалекта Лиспа, где иммутабельность из коробки, впрочем элемент «мутабельности» там тоже присутствует там где это необходимо. И Clojure вполне себе функциональный язык.
Да, это хороий пример функционального языка.
Эм. А какие там функциональные штуки? Немного сахара?
Функции высшего порядка и функции как объекты первого класса были там изначально.

Я не топлю за ФП, просто мимо проходил и увидел странное утверждение.
Я не глубокий специалист в лиспе, надеюсь, кто-нибудь поправит. Знаю только, что есть много разных лиспов: изначальный Лисп МакКарти — совсем императивный, в Common Lisp есть элементы ФП, в Scheme их ещё больше.

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

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

Я к тому, что структуры, внешне выглядящими иммутабельными, для внутренних алгоритмов необязательно должны быть иммутабельными.
UFO just landed and posted this here
Спасибо, посмотрю
Книжка чудо как хороша. И красно-черные деревья там кажется есть.
Стоит понимать что «недостаточно» не значит «невозможно», но излишняя нагрузка на память, иммутабельность и кол-во занимаемого дискового пространство вовсе не шли на пользу развития языка и стоит понимать что я имел ввиду именно чистые функциональные языки на производительность которых жалуются до сих пор, не говоря уже о конце 90-ых
UFO just landed and posted this here

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

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


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

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

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


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


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

Такие двусвязные списки в хаскелле всё равно будут иммутабельные. Ими можно эффективно пользоваться только read-only. Чтобы внести изменение в эту структуру, придется ее полностью перестроить и создать новый список.
UFO just landed and posted this here
Но список же двусвязный. Чем начало отличается от конца? Перестраивать нужно все вершины, достижимые из данной, а для двусвязных списков любая вершина достижима из любой другой. Чтобы избежать недопонимания, я сразу уточню, что я говорю про двусвязные списки, которые получаются при помощи техники, известной под названием tying the knot. Других способов, не использующих монады, получить их я не знаю.
Не совсем правда. Ленивое значение — это как бы «переменная», в которую можно присвоить не больше одного раза. Разве это мутабельноность?

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

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

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

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

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

Да, но и упрощает по сравнению с IORef
Могу рассказать о себе.
Когда я заинтересовался функциональным программированием (где-то в районе 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 имеет смысл учить как первый язык.
UFO just landed and posted this here
Я не особо заморачивался по этому поводу. Один раз память начала расти после отключения печати логов, я просто выкинул генерацию списка с логами. В других до сути не добрался. Сергей Зефиров как-то научился с этим бороться.
Еще о практичности Haskell — в Лаборатории Касперского его используют для кодогенерации в встраевоемой ОС (с помощью библиотеки Ivory). То есть он даже в embedded полезен, особенно с учетем стоимости ошибок.
Игорь Шевнин: Ленивая модель вычислений обычно помогает, но когда порядок вызова функций важен, может быть трудно разобраться, что происходит.

Когда порядок функций важен (например когда надо приготовить файл или написать в базу), вы должны въявную это указывать при помощи 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 мне было сложно определить, что это тоже самое, что и инфиксный оператор «точка»:
.
, но только для функций с двумя аргументами. По мне так, когда в коде встретишь, сразу и не поймешь значение иероглифа, если ранее не встречал такую конструкцию.
Если добавить пробелы или буквы, тоже понятнее не станет.

Ну и что?


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

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


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

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


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

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


glvrd.ru

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

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

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

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

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

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

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

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

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

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

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

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

Вот эта фраза лишает смысла весь ваш комментарий.
UFO just landed and posted this here
>И сравнивать это с джавой — ну такое.
Ну, сравнивать-то можно, очего же нет? Я правда вам скажу, что хорошие проекты на Java делаются примерно так же — путем выделения максимально чистой значимой части, убирания стейта, ну то есть примерно теми же средствами, только инструмент при этом не особо помогает.
Что не так с порядком действий в Хаскельной do?
UFO just landed and posted this here
Почему это должно быть запрещено? Может, автор хочет именно то, что здесь написано — сначала update, потом insert?
UFO just landed and posted this here
Вероятно, автор исходной претензии что-то читал про негарантированный порядок вычислений и не знает, чем вычисление отличается от действия.

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

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

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


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

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


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


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

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


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

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

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

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

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


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

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


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

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

UFO just landed and posted this here
А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.

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


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

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


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

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


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

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

Второй вариант хороший. STM его обеспечивает. Поскольку чтение и запись регистра — императивный эффект, Хаскель обеспечивает порядок. Очень плохо, что в вашем языке последовательность чтений из записей не определена. Переходите на Хаскель.
UFO just landed and posted this here
А вот классификация и типизация вполне себе присуща ежедневным рассуждениям, даже когда вы обсуждаете поход в магазин и покупку каких-то яблок и каких-то стейков, например.

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


Tagless final

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

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

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

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


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

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

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

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

UFO just landed and posted this here
Зачем? Это просто вырождается в partial sort за счёт ленивости.

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


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

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

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


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

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

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

Обращаясь ко всем, хочу сказать следующее. Люди! Haskell — это прекрасно! Учить его полезно любому! Но если вы, как я, поймёте, что не осилили, — не расстраивайтесь: Haskell правда сложный и правда не для всех; я проверил.
Я на прошлых выходных переписал одну утилиту с Go на Haskell — количество аллокаций выросло с 1.5K до 1.5B (миллиардов). Планирую на следующих выходных дебажить и оптимизировать, но быстрый дебаг на 5 минут никакой полезной информации не дал. В свои силы я все еще верю…
Все выводы пришедшие в голову в первые 5 минут — не оправдались. Нужен еще один подход к снаряду.
UFO just landed and posted this here
Спасибо. Меня как-раз удивляло что аллокаций много, а время выполнения маленькое. Я уже issue завел github.com/Twinside/Juicy.Pixels/issues/171
Но, сейчас попробую по вашим рекоммендациям потестировать.
C++ даже сравнивать ни с чем не надо, язык ужасен. Си — хороший язык для низкоуровневой разработки.

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

На сколько я знаю, он же православный!
Лично мне, после знакомства с ООП откровенно «сломать голову» пришлось при ознакомлении именно с Prolog (declarative) нежели чем с Haskel или Lisp (functional). Я считаю, что нужно просто сначала понять парадигму, а потом начинать учить язык.
Всегда удивлял спор о том, что ООП лучше ФП и т.п., так как любой иструмент удобен там, куда он предназначен. Жарить в кастрюле тоже возможно, но не всегда оправдано :)
UFO just landed and posted this here
я потерял покой и сон и нашёл Голдблатта «Топосы. Категорный анализ логики»

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

UFO just landed and posted this here

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

UFO just landed and posted this here
Мне от неё припекает, там всё время отсылки к другим областям математики типа топологии, в которых я не очень шарю, и от которых я всё время чувствовал себя дном.

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

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


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

UFO just landed and posted this here
UFO just landed and posted this here
Неретин Ю. А. "Категории симметрий и бесконечномерные группы".
краткое описание
Книга содержит систематическое изложение теории бесконечномерных групп, их представлений, а также полугрупповых и категорных оболочек. Подробно рассматриваются группа диффеоморфизмов окружности, бесконечномерные аналоги классических групп, группы преобразований пространств с мерой и некоторые группы токов. Обсуждаются также бесконечные аналоги симметрических групп и группы петель. Ряд разделов книги посвящен связанным с конечномерными группами Ли явлениям, которые стали известны лишь благодаря появлению теории бесконечномерных групп. Изложение основано на категорной версии метода вторичного квантования. Для математиков и математических физиков, так или иначе имеющих дело с бесконечномерными группами, а также студентов и аспирантов соответствующих специальностей.

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

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

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

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

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

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

У гитхаба нет поиска по вики. Как этим пользоваться?
Есть плагины для IntelliJ IDEA, Visual Studio Code, Sublime, Atom, Vim, Emacs. Тут уж на ваш вкус.
UFO just landed and posted this here
Скажите, а как сочетается
Не стоит забывать, что еще лет 20 назад железо было не достаточно производительным для функциональных языков, так что в мейнстрим функциональщина начала входить в последние годы, а интерес к Haskell только растет.

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

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

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

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

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

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

Sign up to leave a comment.

Articles