LINUX.ORG.RU

Основывая на чём можно выбрать OCamL или Erlang или Haskell


0

5

Я догадываюсь, что это какая-то паранойа !!! Но как !?

Конечно очевидный вариант - попробовать все. И подумать.

Пробую... Думаю... А дальше что ???

OCamL похож на F#, красив и удобен... хорошо. Применять можно везде, к web имеет много забавных наработок.

Erlang имеет достаточно мощную, стабильную виртуальную машину и синтаксис очень забавный ! Интересный web server yaws и NoSQL DBMS.

Haskell выигрывает по полярности и там есть много действительно хороших библиотек вообще в любой сфере...

Отвечаю на первый предугаданный вопрос - нет, я не хочу на них писать драйвера. Мне интересны сайты, промышленные приложения, утилиты... Но в любом случае я не понимаю как можно их сравнить и выбрать один. Если есть люди, которые выбрали - расскажите как ?


Ответ на: комментарий от tarc

>статическая типизация тут только мешает

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

Декларативщина, что на руби, что на лиспе (тем более без CLOS), крайне нестабильна. Одна небольшая ошибка на нижнем уровне и результат исполнения может очень сильно поменяться... А отследить это можно только в рантайме. Но по закону подлости, сообщение об ошибке будет не то, и не в том месте. Потому что, скорее всего, из-за ошибки на нижних уровнях, сфейлят верхние, когда будут пытаться прожевать неправильные данные. А фейлить они могут ооочень затейливо.

Возьмем, например, создание парсера на хаскеле. Сначала делаем мелкие парсеры, которые возвращают части нашего AST, затем - сводим воедино. Компилятор вывел тип получившегося AST и нам осталось только его зафиксировать. Теперь, если во время оптимизации/рефакторинга/модификации я допущу какую-то мелкую ошибку в самом-самом «нижнем» парсере, например возвращу «1» вместо 1 или возвращу Int вместо Integer, или перепутаю порядок следования парсеров (что изменит структуру получившегося AST), то получу понятную ошибку компиляции, в том месте, где она произошла.

Можно пойти наоборот: сначала разрабатываем нужное AST, а затем «спускаемся вниз». В относительно эзотерической Agda можно вообще «нижние» вычисления чуть ли не автоматом выводить.

Macil ★★★★★
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от tarc

> Кроме того, его гибкость позволяет приминять не мало техник метапрограммирования, доступных в Лиспе

Вобщем-то никакие техники метапрограммирование, доступные в лиспе, в руби недоступны.

anonymous
()
Ответ на: комментарий от Macil

> Но по закону подлости, сообщение об ошибке будет не то, и не в том месте.

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

anonymous
()
Ответ на: комментарий от Macil

> Возьмем, например, создание парсера на хаскеле.

Да ты уже, если честно, утомил со своими peg-парсерами. То, что ты их суешь в каждом треде какбе намекает нам, что других задач, где йоба-типизация заруливает, нет и не предвидится. И еще - аналог таких парсеров (с проверками в рантайме) легко сделать, но не нужно, т.к.:

Теперь, если во время оптимизации/рефакторинга/модификации я допущу какую-то мелкую ошибку в самом-самом «нижнем» парсере, например возвращу «1» вместо 1 или возвращу Int вместо Integer, или перепутаю порядок следования парсеров (что изменит структуру получившегося AST), то получу понятную ошибку компиляции, в том месте, где она произошла.

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

anonymous
()
Ответ на: комментарий от Reset

> в racket'е это лечится контрактами

А еще можно typed racket заюзать - для подобных парсеров его системы типов вполне достаточно.

anonymous
()
Ответ на: комментарий от encyrtid

> считаю, что тем кто пишет прикладное ПО на Plain C нужно гвоздь в голову забить

Т.е. Столлману и Муленару с их редакторами, разработчиками Gnome, мозиллы, апача, ngnix'а, мускля/постгреса, gcc?

Хорошо, что твоим мнением можно только подтереться.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Emacs написан на Elisp + C, Gecko написан на С++, а я говорил о чистом С. Для Гнома на чем только не пишут (на чистом С там GTK и на то есть причины). Я не против С, это хороший язык, я против использования его в качестве прикладного языка, ему в этой нише давным-давно нет места.

encyrtid ★★★★★
()
Ответ на: комментарий от anonymous

Ты немного путаешь: именно порядок вычислений определяет ленивость или энергичность.

А выражение a*b*c при не ассоциативной операции будет давать разные результаты при разной расстановки скобок будь то у тебя язык с ленивым или энергичным вычислением

anonymous
()
Ответ на: комментарий от shty

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

«На любом языке можно написать программу на фортране хаскелле»

Karapuz ★★★★★
()
Ответ на: комментарий от Karapuz

На C# Haskell выглядит очень угрюмым :(

 
private delegate bool ChUname(bool usql, out string uname, out bool rle, out bool ali, out bool cdb, out bool cimp,
                                        out bool parconf, out bool lmts, out bool usrmgm, out bool incdnts);
		private void FRIIB_Load(object sender, EventArgs e)
		{
            gotsql = new Func<bool>(() =>
                {
                    try
                    {
                        ...
                    }
                    catch (Exception)
                    { 
                        ....
                    }
                })();

            if (!(new ChUname((bool usql, out string uname, out bool rle, out bool ali, out bool cdb, out bool cimp,
                                out bool parconf, out bool lmts, out bool usrmgm, out bool incdnts) =>
                    {
                        Func<strc<string,bool,bool,bool,bool,bool,bool,bool,bool>> l = null; l = () =>
                        {
                             .....

nCdy
() автор топика
Ответ на: комментарий от nCdy

На C# Haskell выглядит очень угрюмым :(

если бы это был не Haskell, угрюмости бы не убавилось. что это вообще такое?

jtootf ★★★★★
()
Ответ на: комментарий от vertexua

> Я уже вижу ваш разговор с заказчиками

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

paranormal ★★
()
Ответ на: комментарий от anonymous

>В результате способ «накидать и прогнать тест»

Дело вкуса, на самом деле. Если нравится играть в угадайку с компилятором рантайме — милости прошу.

а они почти всегда наворачиваются не в том месте, где чекер обнаруживает ошибку

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

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

Ты не поверишь, но теория типов это как раз та самая предметная область. Над которой не одно поколение математиков работало :)

Macil ★★★★★
()
Ответ на: комментарий от anonymous

>И на первом же тесте ... экономия времени на отладку

Взаимоисключающие параграфы.

Тесты сами писаться не будут. И они также содержат ошибки.

Да ты уже, если честно, утомил

Ну задай тогда тему...

Macil ★★★★★
()
Ответ на: комментарий от Macil

>> человеческим языком в рамках предметной области

Ты не поверишь, но теория типов это как раз та самая предметная область. Над которой не одно поколение математиков работало :)

бухгалтерский учет например не та самая предметная область

korvin_ ★★★★★
()
Ответ на: комментарий от Macil

>> В результате способ «накидать и прогнать тест»

Дело вкуса, на самом деле. Если нравится играть в угадайку с компилятором рантайме — милости прошу.

а Вы юнит-тесты не пишите?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

>а Вы юнит-тесты не пишите?

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

Macil ★★★★★
()
Ответ на: комментарий от korvin_

>бухгалтерский учет например не та самая предметная область

А бухгалтер эти сообщения не увидит. И не должен.

Macil ★★★★★
()
Ответ на: комментарий от Macil

> А бухгалтер эти сообщения не увидит. И не должен.

он не увидит сообщения, что у него баланс не сходится и список возможных причин?

korvin_ ★★★★★
()
Ответ на: комментарий от Macil

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

так если программа ведет себя корректно, то при чем тут типизация?

mul x y :: Num a => a -> a -> a
mul x y = if x == 123456789 then 42 else x * y

ну вот чем тут поможет стат. типизация?

с другой стороны, если процедура не проходит юнит-тест, значит ошибка в логике (в т.ч. несоответствие типов, но какая тут разница между стат. типизацией и, например, декларациями типов в CL или контрактами Racket? тут разница разве что между обязательностью наличия предусловия и необязательностью, но к статичности/динамичности типизации это в общем-то отношения не имеет) и статичность типизации тут в общем-то не поможет.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> т.е. я к тому, что раз тесты поведения и так пишутся, то зачем вообще статическая типизация?

К тому, что тесты обычно не покрывают 100% кода, а статическая типизация - покрывает.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

К тому, что тесты обычно не покрывают 100% кода, а статическая типизация - покрывает.

тесты не покрывают, да, но прошу покрыть вышеприведенный пример:

mul x y :: Num a => a -> a -> a
mul x y = if x == 123456789 then 42 else x * y
статической типизацией

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> прошу покрыть вышеприведенный пример:

mul x y :: Num a => a -> a -> a

mul x y = if x == 123456789 then 42 else x * y

статической типизацией

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

Внезапно, статическая типизация не гарантирует отсуствия ошибок в программах, но она гарантирует отсуствие ошибок несовпадения типов. И при этом идет постоянная работа над тем, чтобы типы были всё более информативными.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Считаем, что здесь динамическая и статическая типизация сыграли вничью, и этот пример просто ничего не доказывает.

уту, может имеет смысл вынести «типизацию и все такое» во вне языка, в юнит-тесты, но сделать и как бы обязательной частью модуля?

korvin_ ★★★★★
()
Ответ на: комментарий от tailgunner

> Внезапно, статическая типизация не гарантирует отсуствия ошибок в программах, но она гарантирует отсуствие ошибок несовпадения типов. И при этом идет постоянная работа над тем, чтобы типы были всё более информативными.

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

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> контракты (ран-тайм предусловия)

читать как «онтракты (ран-тайм пред-, постусловия)». и, возможно, инварианты и прочее

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

может имеет смысл вынести «типизацию и все такое» во вне языка, в юнит-тесты

То есть вместо проверки типов запускать unit-тесты и надеяться на то 100% покрытие? Нет, не подходит. Потому что кроме разработки нового кода (где статическая типизация полезна, но не критична), есть еще рефакторинг существующего кода. И тут именно статическая типизация рулит - она показывает сразу гораздо больше несогласованностей в коде, чем unit-тест, который вылетает на первой же типовой ошибке.

Кстати... что динамическая типизация имеет сказать по поводу:

def foo(x): return (1 if x == 123456789 else "1")/2

:)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Кстати... что динамическая типизация имеет сказать по поводу:

а зачем ей напрягаться, если первый же юнит-тест сообщит о косяке?

korvin_ ★★★★★
()
Ответ на: комментарий от tailgunner

>То есть вместо проверки типов запускать unit-тесты и надеяться на то 100% покрытие?
Как правило, система начинает работать как следует уже на 60-75% покрытии ;)

malbolge ★★
()
Ответ на: комментарий от tailgunner

> о есть вместо проверки типов запускать unit-тесты и надеяться на то 100% покрытие

т.е. тупо скомпилить статически типизированную программу без юнит-тестов и быть слепо уверенным в ее безошибочности?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> первый же юнит-тест сообщит о косяке

Вот прям-таки первый, да? :) Кстати, заметь, что ошибка может остаться в тексте даже при 100% покрытии.

тупо скомпилить статически типизированную программу без юнит-тестов и быть слепо уверенным в ее безошибочности?

Кхм. Я вроде уже сказал, что статическая типизация не гарантирует отсуствия ошибок? Но зато она всегда анализирует вю программу, в отличие от unit-теста, вылетающего на первом же несовпадении (но вроде я это тоже уже сказал).

tailgunner ★★★★★
()
Ответ на: комментарий от malbolge

>> но она гарантирует отсуствие ошибок несовпадения типов

Согласитесь, этого мало для счастья ;)

После того, как ты согласишься, что без этого счастье невозможно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Вот прям-таки первый, да? :) Кстати, заметь, что есть вместо проверки типов запускать unit-тесты и надеяться на то 100% покрытие

конечно первый:

foo(2)

Traceback (most recent call last):

File «<stdin>», line 1, in <module>

File «<stdin>», line 1, in foo

TypeError: unsupported operand type(s) for /: 'str' and 'int'

ты перепутал == и != =)

но поинт не в этом, а в том, что стат типизация тут тоже вообще не помошник =) а вот, кстати юнит-тест выявит непредусмотренное ветвление и скажет «какого хера тут ветвление?»

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> ты перепутал == и != =)

Ты знал!!1

но поинт не в этом, а в том, что стат типизация тут тоже вообще не помошник =)

Почему нет? Это же пример. В реальности можно перепутать, например, две функции, или забыть указать параметр в вызове, или еще какую-нибудь оидную мелочь.

юнит-тест выявит непредусмотренное ветвление и скажет «какого хера тут ветвление?»

А статическая типизация просто не допустит такой конструкции.

Кстати, где это такие умные unit-тесты?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> А статическая типизация просто не допустит такой конструкции.

это рабостно, но бессмысленно, раз юнит-тест все равно отсеит. двойная работа.

Кстати, где это такие умные unit-тесты?

у одного товарища, пишут софт для авионики.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> рабостно

радостно. пардон, пятница, буквы заплетаются

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

>> Кстати, где это такие умные unit-тесты?

у одного товарища, пишут софт для авионики.

Интересно, скоро ли они изобретут зависимые типы.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Почему нет? Это же пример. В реальности можно перепутать, например, две функции, или забыть указать параметр в вызове, или еще какую-нибудь оидную мелочь.

так же можно много что перепутать, что стат. типизация не распознает, а наивная надежда на ее мощь заставит пропустить в полу"продакшн":

and :: Bit -> Bit -> Bit

and 0 0 = 0

and 0 1 = 1

and 1 0 = 0

and 1 1 = 1

korvin_ ★★★★★
()
Ответ на: комментарий от tailgunner

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

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

> так же можно много что перепутать, что стат. типизация не распознает

Ну третий раз я повторяться не буду.

они там пишут на С++

Внезапно.

tailgunner ★★★★★
()
Ответ на: комментарий от korvin_

>он не увидит сообщения, что у него баланс не сходится и список возможных причин?

Не путай логику программы с бизнес-логикой. Бизнес-логика она либо полностью динамическая, либо нужно в ядро системы загонять какой-то therorem proover типа Agda. Я думаю, это сделают когда-нибудь.

И кстати, систем показывающих почему баланс не сходится, нет. Тебе этого модель бухгалтерского учета не позволит. Т.е. конечно, можно показать какие счета участвуют в формировании тех или иных стаей баланса и даже выявить счета с косячным сальдо, но до выяснения истинных причин, будет как до пекина раком. А какую-то другую модель у тебя бухгалтерия не примет, и правильно, на самом деле. Это задачи для финансовой службы.

Macil ★★★★★
()
Ответ на: комментарий от korvin_

>ну вот чем тут поможет стат. типизация?

Тем, что у тебя будет определено что функция принимает значения с типклассом Num, и возвращает значение с типклассом Num. И никаких других гарантий в данном случае не дается.

Но намного интересен и показателен, например, тип ErrorT String (IO Foo)

Macil ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.