Комментарии 60
Прекрасно.
А работа есть? Кругом джава, Котлин, плюсы, питон, го ...
Говорит то, что на самом деле всех устраивает пользоваться забагованным по и гнаться за качеством (в смысле уменьшения количества багов) особо никому не надо.
С другой стороны если глючит веб интерфейс то и черт бы с ним. А такие системы, где баги приводят к критическим последствиям мало кто пишет. Ну разве что в банковской сфере, борт компьютеры транспортных средств и ПО для электростанций.
Кроме того, ещё говорит о том, что время программистов стоит слишком мало. Одно шуточное высказывание гласит, что у нас вся индустрия - "это борьба с ошибками, чем раньше их найдёшь, тем меньше потери".
Соответственно, если индустрия может сжигать время программистов в написании тестов там, где можно обойтись компилятором, это означает, что программисты продают своё время слишком дёшево. Тесты нужны, но они затратнее расстановки аннотаций типов => должны быть на следующем уровне воронки проверок.
В принципе на проект хватило бы одного-двух. Но да, и столько сложно найти.
Тут скорее проблема что на одного понимающего Хаскел будет 100 вообще не въезжающего в него. А продукт делать надо, у бизнеса есть деньги и он готов попробовать сделать ребенка за месяц.
В принципе при разговоре с импиративщиками нет смысла даже начинать разговор за категории, функторы, естественные преобразования, линзы, монады и т.д. они зациклены на своих стереотипах и шаблонах проектирования.
Просто порог входа повыше и не учат почти нигде. Абстрактная алгебра в массе мало кому даётся на уровне понимания.
За эффективностьб алгоритмов надо обращаться к старым добрым Си или даже к Асм. Хаскель это про другое. Про то, что компилятор берет на себя максимум выявления всех возможных потенциальных ошибок.
И это прекрасно. Будущее наступило, и все языки стали совершенными (даже Бэйсик), благодаря наличию синтаксического анализатора.
Кстати, синтаксический анализатор умеет отследить, что программист по ошибке сложил целое число, которое обозначает количество долларов на счету с другим целым числом, которое показывает сколько на счету евро? Компилятор Хаскеля умеет отслеживать такого рода ошибки (и это далеко не предел). Но это вовсе не значит, что только Хаскель хороший, а все остальные языки отстой. Просто у него действительно есть как сильные, так и слабые стороны и глупо это отрицать.
0xd34df00d порекомендовал бы смотреть в сторону Adga, Idris, но это тоже не панацея.
По поводу второго пункта: будет ли эффективным парсер того же самого zip (да вообще любых файлов, где находится маленькая файловая система; соответственно, чтобы прочитать один файл в это мини-файловой системе не надо читать весь файл (в котором находится эта fs), надо использовать fseek
и прочитать содержимое)? И не скатится ли всё к императивному коду?
Проблема ещё в библиотеках. К примеру, по дефолту нельзя в binary
выбрать, какой будет порядок байтов. По умолчанию Binary
тайпкласс реализован для примитивов так, что порядок байт --- big endian. И как с этим быть?
Я пробовал делать так, но это не работало, если не было -O2
. В любом случае до этого я использовал hGet
и hSeek
. И всё же это облегчает работу, потому что теперь не придётся тащить везде IO
. Заметил, что если два раза попытаться сделать так, как вы сделали, то начинает читаться файл (может, не весь)
Бесстыдно пропиарюсь.
Можно с вами связаться? У меня есть пару вопросов.
Я немного почитал код библиотеки zip, там используется conduit
, а получение первичной информации — информация о самом архиве и файлах, которые в нём есть — вообще происходит так (те самые hSeek
+ hGet
). Так что, как я понимаю, binary-generic-combinators
не особо поможет. Конечно, для того, чтобы спарсить заголовок, может и подойдёт, но всё равно придётся использовать библиотеку наподобие conduit
.
Можно в джаббере, но кто им сейчас пользуется
Я в личку вам написал свой адрес.
А это не вы там про парсинг FAT спрашивали, кстати?
Да, я :\
Удалил сообщение, потому что понял, что не по теме вообще.
Вообще говоря, SML - это стандартный учебный язык. "Введение в стандартный ML" - это жалкие 100 страниц, в которых ядро языка занимает всего лишь 40.
Линзы, категории в программировании и т.д. появились относительно недавно (20 лет для учебного процесса - это ничего).
Вы какую-то уж совсем ерунду пишете.
Главная проблема языка, что контекст его применения очень ограничено и это функциональный язык
Хаскелл — язык общего назначения. Ограничен разве что наличием библиотек для предметной области (GUI для Windows на нём делать, наверное, не очень удобно), ну и embedded или hard realtime на нём не получится (и то, возможны варианты: я как-то писал небольшую прошивку на Си, а команды ей отправлял из Хаскелла).
Функциональный язык — не проблема, а, наоборот, преимущество.
Когда говорят про хаскелль, у меня лично ассоциация с плохим программистом, C++, Java, C, JS, C# не осилил
Интересная ассоциация. Раньше было наоборот: программисты на императивных языках не могли осилить Хаскелл (и так же его ругали, как и вы). Возможно, пришло время, что Хаскелл стал настолько популярен, что кто-то стал учить его как первый язык и не понимать, как работают императивные языки, но что-то я очень сильно в этом сомневаюсь (как и в том, что после хаскелла будет трудно понять императивные языки, скорее будет лучше видно, насколько они неудобны и многословны для большинства задач).
В принципе в разговоре с хаскеллистами нет смысла даже начинать разговор про работу сборщика мусора, про алгоритмы
Настройка сборщика — достаточно распространенное занятие, т.к. это дешевый способ немного ускорить работу программы (настройки по-умолчанию весьма консервативны, хотя их вроде планировали подкрутить в новых версиях GHC), а также ограничить общий объем памяти (утечки из-за невычисленных thunk-ов всё же случаются), дабы в swap не ушло.
Многие алгоритмы в функциональных языках отличаются от императивных. Так что, может быть, ваши алгоритмы просто не подходят?
Хотя императивно в Хаскелле тоже можно (в IO или ST), но это не всегда эффективно, зачастую, как раз из-за сборщика мусора, для которого отслеживание измененных ссылок — головная боль (и в GHC оно, за ненадобностью, не так оптимизировано, как в императивных языках). Хотя есть и unboxed vectors (без нагрузки на сборщик). Можно совсем как в Си писать.
Так что не стесняйтесь — говорите про сборщик и алгоритмы. Мы про это любим.
Они зациклены на своих стереотипах, и мифах
Не стоит всех хаскеллистов стричь под одну гребенку. Многие из них пришли к Хаскеллу как раз после того, как осилили C++, Java, C, JS, C#, и вполне понимают, о чём они говорят.
За этот бредовый наезд (который мог бы показаться жирным троллингом, да боюсь, что вы серьёзно так думаете) вас и заминусовали.
И подтяните русский язык. Если человек не умеет грамотно писать на своём родном языке, то и на языке программирования грамотно писать не получится.
Хаскелл — язык общего назначения. Ограничен разве что наличием библиотек для предметной области (GUI для Windows на нём делать, наверное, не очень удобно), ну и embedded или hard realtime на нём не получится (и то, возможны варианты: я как-то писал небольшую прошивку на Си, а команды ей отправлял из Хаскелла).
ЛОЛ. Вы какую-то ерунду пишите. Вы всегда так себе противоречите в тексте, сами же сначала пишете, что его ограниченная функциональность никак не мешает, а дальше сами же противоречите себе и приводите контраргументы своим словам…
Функциональный язык — не проблема, а, наоборот, преимущество.
А кто писал, что это проблема? Уже придумываете на ходу чего не было написано? Нет там никакой проблемы. Перечитайте внимательное, речь была про ограниченный контекст применения языка. Вы сами же подтвердили мои слова.
Раньше было наоборот: программисты на императивных языках не могли осилить Хаскелл (и так же его ругали, как и вы). Возможно, пришло время, что Хаскелл стал настолько популярен, что кто-то стал учить его как первый язык и не понимать, как работают императивные языки, но что-то я очень сильно в этом сомневаюсь (как и в том, что после хаскелла будет трудно понять императивные языки, скорее будет лучше видно, насколько они неудобны и многословны для большинства задач).
Статистика популярности и вакансий говорит об обратном. Язык появился в 1990 и за это время только отстает в развитии от других, за это время можно было кучу функционала и библиотек написать. Но ничего этого нет и поэтому его контекст применения очень ограничен, поэтому и низкая популярность. Если бы язык действительно решал эффективно какие-то задачи, то был бы в то 10 языков программирования, но он топчется в около 30 месте.
Многие алгоритмы в функциональных языках отличаются от императивных. Так что, может быть, ваши алгоритмы просто не подходят?
Так покажите пример крутого алгоритма на хаскелль. Никто не опроверг моих слов и не показал ни одного примера.
В основе эффективных алгоритмов лежит всегда какая-то эффективная математическая модель. Покажите мне реализацию на хаскелль какого нибудь уникального и эффективного алгоритма.
И подтяните русский язык. Если человек не умеет грамотно писать на своём родном языке, то и на языке программирования грамотно писать не получится.
Кончились аргументы, докопались до орфографии? Только на это хаскеллисты способны? Сестра где примеры? Где пруфы?
-- общее определение (все натуральные числа > 1, которые являются простыми)
primeNums = 2 : [n | n <- [3..], isPrime n]
-- Число простое, если у него нет (простых) делителей
isPrime n = foldr (\p r-> p*p>n || (rem n p /= 0 && r)) True primeNums
foldr — это свёртка списка. Работает так (от b->e или наоборот неуверен):
foldr (fun) a (b,c,d,e) раскрывается в fun(b, fun(c, fun(d, fun (e, a))))
в данном случае fun — это лямбда выражение с двумя аргументами, где p — очередное значение из primeNums, а r — значение с предыдущей иттерации.
Начальное значение — это True, а само выражение лямбды делает следующее:
(\p r-> p*p>n || (rem n p /= 0 && r))
если проверяемое число слишком больше, то автоматом возвращает true, иначе: если на предыдущей иттерации был false, то сразу возвращаем false (ленивые вычисления), и только в противном случае делим и ся результатом.
Понятно, что очень большая нагрузка на оптимизатор: он должен понять, что primeNums возрастающая последовательно, что p*p возрастает по мере возрастания аргумента итд… но если всё это сработает, то получится невероятно оптимизированный алгоритм: для проверки простоты числа N будут проводиться деления только на простые сомножители менее sqrt(N).
Если в чём-то ошибся, надеюсь, более знающие поправят.
ЛОЛ. Вы какую-то ерунду пишите. Вы всегда так себе противоречите в тексте, сами же сначала пишете, что его ограниченная функциональность никак не мешает, а дальше сами же противоречите себе и приводите контраргументы своим словам…
Почитайте определения, чем отличается ЯП общего назначения, от специализированного языка. ЯП общего назначения подходит для большого круга задач, но это вовсе не значит, что для всех задач он подходит одинаково хорошо. Вы некорректно сравнивали Хаскелл с R, языком куда более специализированным, на что я вам и указал.
А кто писал, что это проблема? Уже придумываете на ходу чего не было написано? Нет там никакой проблемы. Перечитайте внимательное, речь была про ограниченный контекст применения языка. Вы сами же подтвердили мои слова.
Вы писали: "Главная проблема языка, что контекст его применения очень ограничено и это функциональный язык"
Статистика популярности и вакансий говорит об обратном.
Она как раз подтверждает то, что программисты на популярных языках не осилили Хаскелл, а не наоборот.
Язык появился в 1990 и за это время только отстает в развитии от других
Наоборот, передовые фичи из Хаскелла переходят в другие языки.
за это время можно было кучу функционала и библиотек написать
Hackage весьма большой.
Если бы язык действительно решал эффективно какие-то задачи, то был бы в то 10 языков программирования, но он топчется в около 30 месте.
На Хаскелл очень эффективно писать сложную обработку данных (компиляторы, например), а это небольшой процент задач. Так же на Хаскелле более эффективно писать и изменять большие программы, но чтобы это понять, надо иметь опыт написания таких программ. Да и мелкие программы (если это не совсем однострочники, где подойдет bash/awk/sed/perl) тоже удобнее писать просто за счет компактного синтаксиса, pattern matching и проверки типов. Но чтобы это понять, надо знать Хаскелл.
Основная проблема в том, что Хаскелл отличается от обычных императивных языков и требует определённого сдвига парадигмы. Учить императивные python, Java, C#, Go, Swift или JS после Си гораздо проще, чем Хаскелл.
Еще одна проблема — legacy. Если проект написан на Java/C++/JS, то внедрить Хаскелл (да и любой другой язык) будет проблематично. По-этому, чаще всего Хаскелл используют во вспомогательных утилитах, или в новых проектах.
Так же, есть проталкиваемые большими корпорациями языки типа Java, Go, Swift, рассчитанные на среднего программиста (обученного императивным языкам) и большие коллективы. Или Си, который приходилось использовать, т.к. на нем написана ОС и больше ничего толком нет. Или JavaScript, кроме которого в браузере ничего не работало.
И не будем забывать про производительность — хорошо оптимизировать программы на функциональных языках научились не так давно, а снижение производительности в несколько раз по сравнению с Си на старых машинах часто было недопустимо.
Так что нет ничего удивительного в том, что Хаскелл не в первой десятке.
Так покажите пример крутого алгоритма на хаскелль. Никто не опроверг моих слов и не показал ни одного примера.
"В основе эффективных алгоритмов лежит всегда какая-то эффективная математическая модель. Покажите мне реализацию на хаскелль какого нибудь уникального и эффективного алгоритма."
Функциональные языки — это, вообще, кузница уникальных алгоритмов.
Избитый пример — балансировка красно-черного дерева, которая на Хаскелл занимает в 10 раз меньше строк, чем на Java.
Еще посмотрите Functional pearls, там много всего:
https://wiki.haskell.org/Research_papers/Functional_pearls
Или почитайте книгу Окасаки "Чисто функциональные структуры данных". Её даже на русский перевели.
Кончились аргументы, докопались до орфографии? Только на это хаскеллисты способны? Сестра где примеры? Где пруфы?
Учитесь вести цивилизованную дискуссию без огульных обвинений и агрессивных выпадов. Тут вроде не анонимная имиджборда.
На вопрос «откуда», нашли в битбакете, а я уж и сам забыл когда им пользовался последний раз.
Мало, но есть. Интересующихся приглашаем в телеграм-чатик #haskell_jobs, куда периодически что-то сыпется.
Аналогичные приемы могут помочь программистам повысить безопасность повсеместно. Продолжая предыдущий пример безопасного хранения пользовательских файлов на сервере – если ваша функция сохранения пользовательских загрузок начинается с
К сожалению, я не нашёл мощной библиотеки работы с путями — пришлось самому делать
data FilePath (p :: [Symbol]) = FilePath (Sing p)
Естественно, в прототипе не было ничего такого, просто импорт библиотеки filepath, которая пытается разбивать строки по слэшам и догадываться, что путь, а что имя файла — ну так и для php должны быть либы с эквивалентым функционалом. Биндинги к windows api/posix тоже приходилось писать на hsc2hs — никакой защиты указателей там нет, потому что C — а что делать? Я к тому, что Хаскелл, конечно, подталкивает к безопасности, но не нужно переоценивать этот эффект.
В связи с этим в пользу Haskell говорит тот факт, что Haskell невозможно хорошо изучить случайным образом. На сегодняшний день Haskell остается достаточно редкой технологией, которая преподается даже не во всех университетах и входит не во все учебные планы.
В первой половине статьи как раз упоминается, что ошибки домена не зависят от технологии. А Хаскелл (Линукс/I2P/Мой-суперкрутой-шифр) — безопасен, потому что Неуловимый Джо — это вообще не аргумент.
Ну вот я слышал про MISRA, и даже частично приходилось пользоваться. И Haskell немножко трогал. И исходя из своего опыта я бы предпочёл Haskell, если бы был выбор. Потому что всякие анализаторы и стандарты — это круто, но из С при этом получается такой обрубок, что пользоваться невозможно. Ada (к вопросу о военных стандартах) на вид неплоха, но уж очень многословно всё.
Минусанул вас кто-то другой, и скорее всего по инерции. Вы же пришли в пост про хаскель и зачем то стали унижать хаскелистов, что мол они даже язык Си не смогли осилить, и поэтому на хаскель переключились. Что мало того, что грубо, так ещё и абсурдно. Скорее всего поэтому и заминусовали.
Да и вообще, откуда у вас такая неприязнь к этому языку? Ну есть такой язык, какой то очень небольшой процент людей на нём пишет. Очень часто just for fun, ибо вакансий чрезвычайно мало. И кому этот язык и эти люди мешают?
В 1999 году… NASA… В ходе расследования… выяснилось, что часть проектировщиков в качестве единицы измерения силы использовала ньютон, а часть — «фунт-силу». Это повлекло за собой ошибку в управлении аппаратами и их гибель.
Я думал, вы так сделали отсылку к тому инциденту.
Но я сам ещё не знаю, как реализовать такую вещь с отсортированным списком и если бы речь зашла о том, что «а ну ка покажи на примере как это делается», то я бы слился. Поэтому я привёл более простой пример (который знаю как сделать).
А, впрочем, зачем выносить, ээ, компоненты путей (это же они, да?) на уровень типов?
Пути не произвольные, там дальше и функции на компонентах есть. Ну и кроме того, очень хотелось синглтоны пощупать, и больное место нашлось.
Но технология позволяет выявлять внутреннюю неконсистентность реализации.
Я уже сильно больше десятка раз находил ерунду в своей формализации одной системы типов только потому, что пытался доказать её свойства на агде.
За агду не скажу, но на хаскелле решал задачу синглтрнами (другую, не с путями) — 5 классов состояний, некоторые комбинации невозможны, некоторые достижимы только из определённых. В целом, мне понравилось — выкинул кучу тестов, потому что тестировать стало нечего, но это всё ещё далеко от математической истины. Наверное, на этих ваших агдах/идрисах/коках можно добиться полного доказательства корректности, но мы же знаем, что дальше хаскелля жизни нет — ни экосистемы, ни сообщества.
Очень интересно, что предотвращает больше ошибок — заумные семигрупоиды в Хаскеле или borrow checker в Rust.
Есть GC — и вся возня с лайфтаймами по большей части не важна.
Универсальный ответ — бенчмаркать надо.
Как меня учили — прежде чем что-то измерять, надо примерно знать, что получишь. ;-) Так что большое спасибо за интуицию.
Смотря что мы обсуждаем
Ну я конкретно обсуждаю определённый класс машин — это типа как последние СПАРКи с полутерабайтом ОЗУ и сотней-другой потоков выполнения. Я не видел систем, кроме make, которые могут легко использовать эти машины так, что действительно появляется их приемущество перед табуном 4-ядерных Linux машин.
То есть, грубо говоря, машина есть, а полностью использовать её достоинства: почти видеокартное кол-во ядер, большая общая память, никто не может — те же задачи можно гонять на большом кол-ве маленьких машинок.
Просто эти монстры уже скоро будут доступны широкой публики => надо как-то уже уметь легко параллелить «обычные» задачи на дикое кол-во потоков. То есть, например, параллельный парсер CSV — у нас же подгрузка данных с NVMe тоже параллельная.
Как меня учили — прежде чем что-то измерять, надо примерно знать, что получишь
Это на курсах по P-fishing что-ли? Измерено значит измерено, дальше вопрос можем ли понять что именно было измерено и с какой погрешностью.
Вот чем больше я знакомлюсь с Rust, тем меньше я считаю, что главная задача borrow checker — это управление мусором.
На самом деле концепция ownership позволяет контролировать coupling между посистемами. Если мы даём reference, то мы обязаны заботиться о нём. Это не обязательно память. Это может быть открытый fd, принятый http запрос и т.д.
Если мы отдаём ownership, то мы перестаём думать про этот объект. Например, диспетчер http-запросов будет раскидывать запросы в воркеров с передачей владения, если он это сделает через reference'ы, то ему придётся за ними следить. Это будет очень сложно, архитектурно.
Система borrow checker не улучшает ситуацию, она просто выводит архитектурные ошибки на уровень компиляции. Например, передать reference в соседний тред почти никогда не возможно (и так делать не надо). Синтаксис Rust запрещает это, остальные языки не могут ничего сказать про эту проблему.
На самом деле концепция ownership позволяет контролировать coupling между посистемами.
К сожалению, когда защита слишком неудобная, её обходят. Я видел, что вместо передачи объекта во внутреннюю функцию (которая просто перепаковывает его и пересылает по сети), его клонируют, и передают клон.
Система borrow checker не улучшает ситуацию, она просто выводит архитектурные ошибки на уровень компиляции.
Видимо это и есть корень нареканий на borrow checker — он слишком поздно показывает проблемы. Ведь на этапе компиляции часто слишком поздно исправлять архитектурные ошибки. Особенно, если архитектура уже где-то используется.
Спасибо!
Ведь на этапе компиляции часто слишком поздно исправлять архитектурные ошибкиОт этого тоже есть польза. Если он причиняет программисту боль, в следующий раз он уже будет научен и продумает архитектуру заранее, чтобы больше не наступать на граблю.
Если он причиняет программисту боль, в следующий раз он уже будет научен и продумает архитектуру заранее, чтобы больше не наступать на граблю.
Как всегда, две стороны:
1. Да! И об этом ему надо рассказать, открыть глаза! :-)
2. К сожалению, часто одним приходится платить за ошибки других — архитектура может быть задана заранее. :-(
В тот момент, когда bc вам мешает, и вы значение клонируете, то есть вероятность, что это разумное решение для обеспечения разумности поведения. Т.е. (за вычетом проблем с disjoint borrows у структур) bc просто запрещает плохие действия. Иногда не очевидно, где это укусит, но бывает так, что потом становится понятно — что действительно, bc был прав.
Haskell – хороший выбор с точки зрения безопасности ПО?