Скорее реально, лучше распишу полностью, чтобы не было недоговоренного, или если что меня бы поправили. Изначально Haskell академический язык и песочница для различных исследований и проверки концепций, до ~95 года (т.е. около 5 лет существования языка) в нём нельзя было делать полноценного IO и программа это была или подача строки на вход и оно выдавала строку на вывод, или чуть-чуть расширенный набор примитивов. Называть такой язык не исследовательским языком тяжело и языком на котором можно писать программы тяжело. Однако среди авторов языка и тех кто с ним работал были и люди, которые двигали его в сторону, где его использование в общем случае было бы возможно. В районе ghc-6.12 уже стало достаточно пристойно, хотя и все равно было много вопросов. В общем-то языком, на котором можно писать полезные программы он стал не так и давно, и в планах изначально этого не было, просто так получилось.
версия PHP 4 тут при том, что является примером моему утверждению, а brainfuck нет. Пример был необходим, чтобы больше не возникало идей для передергиваний.
Создателями обычно двигает знание языка, знание похожих языков, наличие готовых библиотек, наличие знаний у команды. Возможно то, что вы называете «субьективной легкостью вхождения». Наприме, если у вас тут есть команда людей на OCaml, а вам нужно написать сложный проект, с большим количеством шаблонного кода, то вы возьмете MetaML, а не go, python или что-либо ещё, на что команда явно потратит больше времени на изучение.
Ещё раз повторюсь, язык не должен быть хорошим, для того чтобы на нём можно было успешно писать, он должен быть достаточным, чтобы на нём ваша команда могла решать поставленные перед вами задачи, а его экосистема должна иметь нужные вам средства для работы (библиотеки/утилиты/документацию/статьи). В го нету очень многого, с точки зрения CS это огромный шаг назад в развитии, никакого анализа решений на рынке, результатов в науке — это плохо? Ну с точки зрения программиста, наверное да, но только когда эти возможности ему нужны. Т.е. в обем-то ответ на половину упрёков (разумных естественно), может быть «да, плохо, решается так (ссылка), ну и что дальше?».
Например, тот же haskell тоже далеко не идеален, метапрограммитование только generic-s (не путать с явовыми) и ужасный TempateHaskell, kinds equal types нету, т.е. никаких там зависимых типов (кроме костылей с синглетонами), function patterns — нет не завезли, и это если не углубляться, причем в разных языках рядом все это есть, но для решения повседневных задач это не нужно.
Haskell создан для того, чтобы был основной язык для изучения свойств ленивых функциональных языков. В то время на этой нише не было ни одного подобного языка, а запрос был, впрочем за последние 20 лет ситуация не изменилась.
То, что на Haskell оказывается можно ещё и код писать, это счастливая случайность. И за последние годы Haskell экосистема заметно продвинулась в данном направлении.
Вы сознательно пропустили часть процитировнной Вами фразы? Бреинфак, не является разумным образом, достаточным для написания веб фреймворка. PHP, например, является, и несмотря на все проблемы языка, особенно в версиях 4.x мы можем видеть множество решений на нём.
Соглашусь, что из моей фразы совершенно непонятно почему иногда наблюдаются мирграции на язык с меньшими проблемами, но это нужно гораздо точнее формулировать фразу или сильно расписывать, а мне лень.
я честно не понимаю сути такого сравнения языков, а тем более приведения в качестве какого-либо аргумента успешные проекты.
Причем на доводы о том, что в языке чего-то не хватает, или что какие-то вещи реализованы неверно, приводятся агрументы, вида
«а мне/успешному проекту, оно не нужно» или «а зато у нас докер». Как будто, что-либо мешает писать на языке успешные продукты,
ну плохой язык, ну и что, вещи практически независимые, в итоге максимальной популярностью обычно начинает пользоваться самый плохой инструмент из достаточных для решения задачи. А успешность написания программ зависит от качества программистов и менеджеров. Особенно аргумент про продукты тоже интересен, я подозреваю, что в NY больше го программистов, чем программистов на Haskell, пишущих публичные продукты, так что результат не сильно удивителен.
> Все остальные сообщения приводят к ошибке (и, кажется, то ли просто игнорируются аккой, то ли приводят к падению актора, не помню).
вот это важно, например, в cloud haskell, есть примитив receiveWait, который позволяет обрабатывать сообщения таким же образом, при этом можно явно контролировть, что произойдёт с остальными сообщениями (в случае добавления matchAny они будут прочитаны из MailBox и их можно обработать, иначе они там остаются).
В остальном, никакой разницы между Erlang (насколько я его знаю) или Haskell я лично не заметил, код так пишут всегда…
Однако параметрический полиморфизм, то, что в java почему-то назвается Generics, (без подтипирования) появился аж в 1975 году, так что это не оправдание. Кстати, это же объясняет почему, в Go его нету, туда настолько молодые фичи не попадают.
TH это, кстати канонический пример костыля, т.к. радостно ломает абстракции (скрывает типы за ExpQ), в отличии от Generics, и даже появляющийся Typed-TH не очень поможет в силу ограничений. (Правда в отличии от generics позволяет генерировать более эффективный код, с расширениями generics такое тоже возможно, но уже не так просто). Естественно плюс TH, в отличии от, насколько я понимаю, go, в том, что генерация производится средствами языка, что не мешает вызывать внешние утилиты если необходимо. А совсем хороший вариант в MetaOcaml, например.
Мне каждется, доказать то, что это обман достаточно просто, для этого все лишь нужно указать ссылки на статьи. Если язык не базируется на статьях, то можно попытаться агрументировать тем, что это хороший инженерный язык, и привести в доказательства рассылки и статьи в блог постах авторов, объясняющие решения, обосновывая это технически. К сожалению это будет доказательстов того, что язык построен на ad-hoc решениях (ну или костылях, смотря какая агрументация).
С такими характеристиками стоит на zadolba.li писать, а истории про себя правильного на ithappens. А этот сайт ведь когда-то чисто техническим считался, где хорошим тоном было писать статьи без ложных предпосылок, не забывая четкие аргументы, а при сравнения объективно рассматривать обе стороны в рамках своего понимания.
Мне кажется, что утверждение было «в хорошем вопросе содержится половина ответа», не уверен, что из этого следует, то что её нужно знать, во всяком случае осознавать.
Впрочем это не важно, даже не зная половины ответа можно начать дискуссию и сайты (кроме сайтов вопросов) для этого и созданы, это поможет выяснить разницу и ошибки в понимании (возможно и у отвечающих). Просто в данной статье я заметил, некоторые вещи, которые меня удивили, так то: описание ожидаемого, не учитывание принципов работы выбора инстанса, неаккуратное соотвествие в записи того, что хочется получить и что делается (комментаний про Rank2Types). Я не знаю является ли это непониманием, или просто неточной формулировкой или неточным моим прочтением, но преварительный разбор частей бы не помешал :)
Может это слегка грубо, но мне кажется, что единственный вывод, который можно тут сделать это то, что перед тем, как писать статью стоит зайти на сайты где можно получить подробные ответы на вопросы и удостовериться, что вы правильно понимаете обсуждаемые вопросы. Примеры таких сайтов это (stack-overflow по тегу haskell, #haskell на freenode.net, рассылка Haskell-Beginners или haskell-cafe (в первой наверняка ответят подробнее), вопросы на хабрахабр, так же есть неплохие сообщества в LJ, Juick.com, ruhaskell.org).
это конечно не очень хорошо с моей стороны, но позвольте поинтересоваться, была ли у вас на хакатоне возможность обращаться к книгам, интернету, или общаться с сообществами языков. Просто уж за два то (рабочих) дня при наличии обучаеющего человека можно получить очень неслабое введение в язык, вплоть до того, что потом быть способным работать в команде, в которой есть 1-2 хорошо разбирающихся человека.
уже ниже привел пример, чтобы лучше понять как оно работает. Существует достаточно простое правило:
если вы знаете, что вам нужна ленивость в поле, т.е. это как-то используется алгоритмами — то не делайте его строгим, в противном случае — делайте
.
Данное правило не совсем хорошее, поскольку на каком-то этапе можно упустить случаи, когда ленивость поможет.
Примеры структур, где нужна ленивость, например структуры использующие для построения завязывание в узел или результаты из «будущего», структуры для мемоизации, структуры в которых хранятся значения большая часть из которых может быть не вычислена, бесконечные структуры. При этом вычисления на ленивых стуктурах проще объединяются (compose)
Примеры структур, где ленивость вредна, элементараные структуры, которые могут накапливать вычисления, например:
`foldl' (\(x, y) c -> (x+c, y*c)) (0,1) [...]` несмотря на то, что свертка строгая в «полях» кортежа будет накапливаться вычисления и вычеслены будут только вконце.
Учитывая сказанное выше, я бы сказал, что строкими нужно делать поля во всяких пользотельстких структурах, на которых не строится control flow.
data A = A Int
data B = B Int
data C = C ![Int]
mk constr conv = const . conv
Далее в интерпретаторе:
> let a = mk A id 7
> :sprint a
a = _ -- у нас thunk вместо значения
> (\x@(A _) -> True) a -- вычисляем до WHNF
True
> :sprint a
a = A _ -- конструктор вычислен в поле Thunk
> let b = mk B id 8
> :sprint b
b = _
> (\x@(B _) -> True) b
True
> :sprint b
b = B 8 -- конструктор вычислен и поле тоже вычислено
*Main> let c = mk C id (replicate 7 9)
*Main> (\x@(C _) -> True) c
True
*Main> :sprint c
c = C (9 : _) -- как видим поле вычислено только до WHNF
Сделать поле строгим. Т.е. если данные вычисляются то WHNF (weak head normal form), то и поля отмеченные строгими вычисляются до WHNF. Помогает избежать излишних отложенных вычислений в структурах данных и является общим правилом (уже практически принятым с сообществе).
А ну ясно. Про странность сравнения согласен. Хотя в общем-то можно показать сколько накладных расходов вносит web framework… Не в курсе, что OK для Habrahabr, что нет…
> Text — тип данных, предназначенный как для ASCII, так и для UTF-символов. Находится в библиотеке text и существует в двух видах: строгой и ленивой. Подробнее — здесь
Тип данных предназначенный для хранения текстовой информации внутри программы. В Text хранятся UTF-16, т.е. не может представить все множество представимое типом Char. Является unpinned, т.е. данные могут перемещаться сборщиком мусора. Поддерживает stream-fusion, т.е. операции поддерживающие stream fusion объеденятся в одну мегаоперацию, которая не создает промежуточных структур. Т.е., например, `T.replace «a» «ab». T.replace «c» «de»` не будет создавать промежуточную строку между операциями replace (требует хотя бы -O). Но при этом не поддерживает эффективные блочные операции.
> ByteString — предназначен для сериализации строк в поток байтов. Поставляется в библиотеке bytestring и также в двух вариантах: строгом и ленивом.
Очень неточное высказываение. Тип данных ByteString предназначен для представления бинарных данных, IO взаимодействий и взаимодействий с внешними функциями (FFI). ByteString представлен массивом байтов (Word8). ByteString является pinned, т.е. гарантировано не будет перемещен сборщиком мусора (что может приводить к фрагментации памяти). Не поддерживает stream-fusion в полной мере. Может использовать блочные операции. В новых версиях есть ShortByteString являющийся unpinned.
Создателями обычно двигает знание языка, знание похожих языков, наличие готовых библиотек, наличие знаний у команды. Возможно то, что вы называете «субьективной легкостью вхождения». Наприме, если у вас тут есть команда людей на OCaml, а вам нужно написать сложный проект, с большим количеством шаблонного кода, то вы возьмете MetaML, а не go, python или что-либо ещё, на что команда явно потратит больше времени на изучение.
Ещё раз повторюсь, язык не должен быть хорошим, для того чтобы на нём можно было успешно писать, он должен быть достаточным, чтобы на нём ваша команда могла решать поставленные перед вами задачи, а его экосистема должна иметь нужные вам средства для работы (библиотеки/утилиты/документацию/статьи). В го нету очень многого, с точки зрения CS это огромный шаг назад в развитии, никакого анализа решений на рынке, результатов в науке — это плохо? Ну с точки зрения программиста, наверное да, но только когда эти возможности ему нужны. Т.е. в обем-то ответ на половину упрёков (разумных естественно), может быть «да, плохо, решается так (ссылка), ну и что дальше?».
Например, тот же haskell тоже далеко не идеален, метапрограммитование только generic-s (не путать с явовыми) и ужасный TempateHaskell, kinds equal types нету, т.е. никаких там зависимых типов (кроме костылей с синглетонами), function patterns — нет не завезли, и это если не углубляться, причем в разных языках рядом все это есть, но для решения повседневных задач это не нужно.
То, что на Haskell оказывается можно ещё и код писать, это счастливая случайность. И за последние годы Haskell экосистема заметно продвинулась в данном направлении.
Соглашусь, что из моей фразы совершенно непонятно почему иногда наблюдаются мирграции на язык с меньшими проблемами, но это нужно гораздо точнее формулировать фразу или сильно расписывать, а мне лень.
Причем на доводы о том, что в языке чего-то не хватает, или что какие-то вещи реализованы неверно, приводятся агрументы, вида
«а мне/успешному проекту, оно не нужно» или «а зато у нас докер». Как будто, что-либо мешает писать на языке успешные продукты,
ну плохой язык, ну и что, вещи практически независимые, в итоге максимальной популярностью обычно начинает пользоваться самый плохой инструмент из достаточных для решения задачи. А успешность написания программ зависит от качества программистов и менеджеров. Особенно аргумент про продукты тоже интересен, я подозреваю, что в NY больше го программистов, чем программистов на Haskell, пишущих публичные продукты, так что результат не сильно удивителен.
вот это важно, например, в cloud haskell, есть примитив receiveWait, который позволяет обрабатывать сообщения таким же образом, при этом можно явно контролировть, что произойдёт с остальными сообщениями (в случае добавления matchAny они будут прочитаны из MailBox и их можно обработать, иначе они там остаются).
В остальном, никакой разницы между Erlang (насколько я его знаю) или Haskell я лично не заметил, код так пишут всегда…
Впрочем это не важно, даже не зная половины ответа можно начать дискуссию и сайты (кроме сайтов вопросов) для этого и созданы, это поможет выяснить разницу и ошибки в понимании (возможно и у отвечающих). Просто в данной статье я заметил, некоторые вещи, которые меня удивили, так то: описание ожидаемого, не учитывание принципов работы выбора инстанса, неаккуратное соотвествие в записи того, что хочется получить и что делается (комментаний про Rank2Types). Я не знаю является ли это непониманием, или просто неточной формулировкой или неточным моим прочтением, но преварительный разбор частей бы не помешал :)
.
Данное правило не совсем хорошее, поскольку на каком-то этапе можно упустить случаи, когда ленивость поможет.
Примеры структур, где нужна ленивость, например структуры использующие для построения завязывание в узел или результаты из «будущего», структуры для мемоизации, структуры в которых хранятся значения большая часть из которых может быть не вычислена, бесконечные структуры. При этом вычисления на ленивых стуктурах проще объединяются (compose)
Примеры структур, где ленивость вредна, элементараные структуры, которые могут накапливать вычисления, например:
`foldl' (\(x, y) c -> (x+c, y*c)) (0,1) [...]` несмотря на то, что свертка строгая в «полях» кортежа будет накапливаться вычисления и вычеслены будут только вконце.
Учитывая сказанное выше, я бы сказал, что строкими нужно делать поля во всяких пользотельстких структурах, на которых не строится control flow.
Тип данных предназначенный для хранения текстовой информации внутри программы. В Text хранятся UTF-16, т.е. не может представить все множество представимое типом Char. Является unpinned, т.е. данные могут перемещаться сборщиком мусора. Поддерживает stream-fusion, т.е. операции поддерживающие stream fusion объеденятся в одну мегаоперацию, которая не создает промежуточных структур. Т.е., например, `T.replace «a» «ab». T.replace «c» «de»` не будет создавать промежуточную строку между операциями replace (требует хотя бы -O). Но при этом не поддерживает эффективные блочные операции.
> ByteString — предназначен для сериализации строк в поток байтов. Поставляется в библиотеке bytestring и также в двух вариантах: строгом и ленивом.
Очень неточное высказываение. Тип данных ByteString предназначен для представления бинарных данных, IO взаимодействий и взаимодействий с внешними функциями (FFI). ByteString представлен массивом байтов (Word8). ByteString является pinned, т.е. гарантировано не будет перемещен сборщиком мусора (что может приводить к фрагментации памяти). Не поддерживает stream-fusion в полной мере. Может использовать блочные операции. В новых версиях есть ShortByteString являющийся unpinned.
Как-то так.