OCaml vs (Haskell & Scala)

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

На протяжение вот уже 3-х месяцев я изучаю OCaml. Мне сразу понравилась природа чисто функционального подхода, при котором большинство алгоритмов становятся проще в понимании, несмотря на то, что иногда у меня возникают затруднения в их реализации.

В силу того, что я до сих пор новичок в OCaml, мне было бы интересно сравнить его с другими функциональными языками. Не с позиции наличия тех или иных библиотек или синтаксических особенностей (www.haskell.org/haskellwiki/OCaml ). Хотелось бы услышать мнение тех, кто по каким либо причинам (и по каким) выбрал для себя OCaml, а не SML (по типу Scala или Haskell)

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

вот как раз сегодня jane-street выложили: blogs.janestreet.com/why-ocaml

Возвращаясь к теме 23-летних Java-сеньоров — “How to Learn Haskell in Less Than 5 Years”:

www.youtube.com/watch?v=Bg9ccYzMbxc

+ bitemyapp.com/...functional-education.html
(более-менее тоже самое что и в докладе, если не ошибаюсь)

Хотелось бы услышать мнение тех, кто по каким либо причинам (и по каким) выбрал для себя OCaml, а не SML (по типу Scala или Haskell)
когда смотрел Standard ML мне он понравился (ну я его правда самые основы посмотрел, возможно на новогодние праздники еще его посмотрю), а вот Ocaml почему-то «не зашел» с первой попытки. Возможно вся проблема в винде (окамл все-таки больше под юниксы заточен насколько понимаю).
С другой стороны понравился (и вроде как понятен) F#)

насчет скала vs. хаскель: изучаю потихоньку хаскель — нравиться, скалу еще не смотрел, но пока не особо в нее тянет (но думаю тоже как-нить ее пощупать).

Интересно, как топикстартер относиться к F#? родственный окамлу язык как никак.

З.Ы. и да, что изменилось то за 2,5 года у ТС со времени написания поста? освоил окамл?

все это слабо применимо практически

а вот в качестве тренировки для погроммистских мозгов (то есть, далеко, далеко не для всех и каждого) — то шо надо

странно что товарищ занят абстракциями и алгоритмами вместо практики написания реальных web приложений на ocaml. слабо сделать CMS на том же ocsigen,м?

В Haskell хорошо сомотреть, как из идеи «сделаем чистый ленивый язык» рождаются интересные практические решения

В Scala интересные возможности для метапрограммирования и возможность использовать JVM.

В Closure — меньше пахнет явой :)

Если JVM не подходит, а .NET/CLR — самое оно, то F#

А если хочется совсем без виртуальной машины — то OCaml

Как-то так.

Метапрограммирование было упомянуто в пункте со Scala, но не в пункте с Clojure? Не путаете ничего? Недомакросы Scala, это вам не полноценная среда Lisp/Scheme. У скалы есть зато десятки других фич, при этом не понятно почему метапрограммирование у вас считается основной

Хотел написать «В Closure — то же самое, но меньше пахнет явой», но не дописал :(

Метапрограммирование я поставил на первое место, т.к. имено оно мне интереснее всего. Принципиальной разницы в том, что можно сделать в scala и closure я не вижу, но я могу ошибаться, т.к. каждый день ни на том ни на другом я не пишу.

Очевидно, критерій тут «[в Clojure] не треба трахатись, значить несерйозно».

то F#
Мертворожденое дитя майкрософта

Дисклеймер: OCaml не знаю.

OCaml мені здається більш академічною мовою, ніж Хаскель, але це, можливо, через те, що математичні кути Хаскеля при використанні стерлись для мене. Втім, я б не прирівнював «математичність» (яка в Хаскелі часто просто зводиться до використання страшних термінів із теоркату, хоч все просто; до того ж, те, що в Хаскелі називається монадою, ніхто на монадні закони не перевіряє) і академічність.

Перевагою Хаскеля вважаю те, що він чисто функціональний і не дозволяє ефектів на рівні мови (наскільки знаю, OCaml не має монадних гарантій і дозволяє IO будь-де), хоч з таким самим успіхом можна сказати, що це його недолік, який заважає практичному використанню.

Щодо компіляторів і реалізацій, то вважаю GHC сильним аргументом за Хаскель в плані паралельності та надійності (спарки, автоматичне розпаралелення, профілювання, — виправте, якщо щось із цього є в реалізаціях OCaml). Але, з другого боку, швидкість скомпільованого OCaml може бути значно більше.

У Хаскеля також є hackage та cabal, які є досить непоганим джерелом бібліотек (хоч у cabal і є свої проблеми, але в ньому, наприклад, не проблема знайти байндинги навіть до FUSE та OpenGL), не знаю, як із цим у OCaml. Також із практичної точки зору у Хаскеля дуже пристойний як на функціональну мову FFI.

У окамла в качестве альтернативы hackage/cabal-install есть opam. Там еще мало всего, но оно набирает обороты

OCaml — это функциональщина с ООП возможностями, Scala — ОПП язык с функциональными возможностями, Haskell — чистая функциональщина. Из вышеперечисленных используется только Scala и то редко. Если OCaml нравится действительно сильно, то имеет смысл посмотреть F# - там можно сделать что полезное, благодаря .net библиотекам. Правда всё равно придётся использовать C# или VB.net для управления формой, ибо кодогенераторы для F# отсутствуют.

Тут надо уточнить, что на F# надо смотреть, если mono в качестве целевой платформы полностью устраивает.

Если запускать на *nix-ах — то лучше таки ocaml, а не F#

Интересно, что вопрос почти слово в слово отсюда: stackoverflow.com/...skell-sml-scala

То есть это было признание в попытке затроллить меня гуглением схожих тем на SO? Или порыв графоманства без представления о предмете обсуждения

То есть это было признание в попытке затроллить меня гуглением схожих тем на SO

Банальнее: у меня примерно схожая ситуация; не определился что мне нравится больше — haskell or ocaml.

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

Или порыв графоманства без представления о предмете обсуждения

Хам

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

пф и не сложиться

я тебе уже отписал в основной ветке топика

Согласен. Но ради справедливости стоит заметить что лисп — не лисп со статической типизацией. И лисп — не лисп без скобочек (s-выражений). У него есть некоторые фичи исключительно из-за этих особенностей.

Lisp хороший для того, щоб його реалізовувати, а не для того, щоб на ньому щось реалізовувати. OCaml має бути набагато краще в цьому плані.

пользователи emacs возразят вам с пеной у рта (: еще как-то проскакивала пара инсайдов из недр крупных бирж, но без пруфлинка к сожалению =(

От крім emacs лісп особливо і не використовується, наскільки я бачу. І то знавці розкажуть про жахи динамічного scope змінних в elisp.
Ну і я не кажу, що на ліспах _неможливо_ писати, просто що більшість задач робляться приємніше в мовах із людським синтаксисом і хорошою статичною типізацією.

лісп особливо і не використовується

На вашем десктопе

Lisp хороший для того, щоб його реалізовувати, а не для того, щоб на ньому щось реалізовувати. OCaml має бути набагато краще в цьому плані.
От крім emacs лісп особливо і не використовується, наскільки я бачу.
А окамл типа используют? Хоть где-то? Хоть в емаксе?

P.S. В Автокаде, вроде как, внутренний язык диалект лиспа.

как то так vimeo.com/14313378
И че? Может перескажете своими словами где там ответ, а то смотреть 1+ час лень.
Догадка с потолка: В финансовых приложениях (или в научных). Если да, так лиспы и всякие смолтоки там так же используют.

В двух словах на видео: статическая типизация очень помогает когда ошибки не простительны(хотя относительно больше кода). OCaml компилируемый(пусть и для vm) поэтому быстр. Используют там где выше указанное нужно. В этом случае это финансы.

статическая типизация очень помогает когда ошибки не простительны(хотя относительно больше кода).
Для этого есть тесты. Статическая типизация — это не преимущество и не недостаток, это просто другой подход.
OCaml компилируемый(пусть и для vm) поэтому быстр.
clojure? Есть компиляторы лиспа, которые генерят машинный код. И че?
В этом случае это финансы.
Таки угадал :) В финансах используют очень много чего, от только это не про преимущества, а про «контингент», например там много людей из академической среды.

Статическая типизация — она для того, чтобы не писать банальные тесты. И чтобы рефакторить было проще (намного проще).

Статическая типизация — она для того, чтобы не писать банальные тесты.
Не понял. Поясните подробнее, желательно с примером.
И чтобы рефакторить было проще (намного проще).
Не проще, а __по другому__. Для авторефакторинга таки проще, но тут многое зависит от стиля использования. Простой пример: джаваскрипт написанный в стиле «ООП с классами» очень легко понимает любая ИДЕ.

Думаю имелось ввиду что много тестов динамических ЯП содержат проверки «есть ли поле name в возвращаемом результате». Если забыли где-то покрыть, потом удалили name, то вылезло лишь потом на продакшне в каком-то всеми забытом диалоге.

В статике эту роль играет тип и ошибка компиляции. Можно считать это своеобразным, уже написаным тестом. И пример упрощенный. Хуже когда какая-то Map[Int,List[Map[String, Double]]] меняет свою структуру. Даже если разбить все по классам чтобы не допустить такой дебильной структуры, ошибки в изменении структуры все равно могут вылезать.

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

много тестов динамических ЯП содержат проверки «есть ли поле name в возвращаемом результате»
Не только тесты, но и рабочий код изобилует такими условиями, но если мы изначально берем динамический язык, то предполагается, что мы осознаем как этот случай использовать себе на пользу. Поле в значение null/None и т.п. может прийти из обращения к стороннему API, например. Статическая типизация тут не спасёт.
Если тесты у вас служат для валидации структур данных — то что-то не так в датском королевстве.
Поле в значение null/None и т.п. может прийти из обращения к стороннему API, например

Я думаю есть разница когда и API и Client API осознают что поле name по идее есть (хоть может быть и null), или когда это лишь допущение клиента согласно документации не первой свежести. И я уже сказал, многие фреймворки JS присылают обьект такой большой сложности что определиться самому, при отсутствии доков, что делать с этим обьектов трудновато

Если в структуре данных явно не указано, какое поле может стать None — то что-то не ладно в датском королевстве :)

Думаю имелось ввиду что много тестов динамических ЯП содержат проверки «есть ли поле name в возвращаемом результате».
По руках!! Нормальные люди проверяют значение, и если поля нет, то (сюрприз) его значение не совпадет с ассертом.
Хуже когда какая-то Map[Int,List[Map[String, Double]]] меняет свою структуру.
Если есть адекватные тесты, то при изменении типов у вас свалятся тесты. Если нет, то тут уже проблема чуть глубже.

Про тесты:
1)Не пишем тестов «входые или выходные данные — определенной структуры» (как уже указали в соседнем ответе)

2)Не пишем тестов, которые суют выход функции foo на вход функции bar просто для того, чтобы при изменении foo «вот тут сломалось и мы поменяли и bar тоже»

3)Не пишем тестов вида «У нас 10 опциональных полей, логика зависит от того, какие из них есть, надо написать тесты, который проверит, что мы ни одного возможного варианта не пропустили»

Про рефакторинг:
Я не про «переименовали Foo в Bar», я про «без всякой автомагической поддержки со стороны IDE разобьем этот модуль на 4 отдельных, у вот этих двух структур полностью изменим представление, и заодно поменяем внешний интерфейс у библиотеки». Я видел, как люди это делают без поддержки со стороны статически типизирующего компилятора, и мне это не нравится :)

1)Не пишем тестов «входые или выходные данные — определенной структуры» (как уже указали в соседнем ответе)
Незачем. (как уже ответил выше)
2)Не пишем тестов, которые суют выход функции foo на вход функции bar просто для того, чтобы при изменении foo «вот тут сломалось и мы поменяли и bar тоже»
Это называетсо интеграционные тесты. Так вот статическая типизация не отменяет этих тестов.
3)Не пишем тестов вида «У нас 10 опциональных полей, логика зависит от того, какие из них есть, надо написать тесты, который проверит, что мы ни одного возможного варианта не пропустили»
И не пишем тестов вида:
«У нас 10 опциональных полей, логика зависит от того, какие из них _установнены в некоторое значение_, надо написать тесты, который проверит, что мы ни одного возможного варианта не пропустили»
Отсутствие поля — это лишь дополнительное значение этого поля.
разобьем этот модуль на 4 отдельных, у вот этих двух структур полностью изменим представление, и заодно поменяем внешний интерфейс у библиотеки
Отбросить тот момент что это надо разбивать на несколько шагов.
Я видел, как люди это делают без поддержки со стороны статически типизирующего компилятора, и мне это не нравится :)
Я делал подобный рефакторинг и не вижу проблем.
Это называетсо интеграционные тесты. Так вот статическая типизация не отменяет этих тестов.
Сложные интеграционные тесты — не отменяет. Тривиальные — вполне себе отменяет
Отсутствие поля — это лишь дополнительное значение этого поля.
Угу. И статическая типизаци помогает проверить, что наша логика (при использовании pattern matching) покртывает все возможные варианты нашей структуры. => можно не писать тесты.
Отбросить тот момент что это надо разбивать на несколько шагов.
Зачем? В чем сложность?
Я делал подобный рефакторинг и не вижу проблем
Я не говорю, что это невозможно. Я говорю, что с типизацией это проще. Практически все места, которые надо подправить, автоматически найдет компилятор => я могу тратить свои силы на что-то более плодотворное.
Сложные интеграционные тесты — не отменяет. Тривиальные — вполне себе отменяет
И снова, тривиальные это какие? На ваш пример:
f = func(){
b(a(x))
}
Надо покрывать тестами, поскольку статическая типизация не покрывает такое изменение:
f = func(){
b(c(a(x)))
}
И статическая типизаци помогает проверить, что наша логика (при использовании pattern matching) покртывает все возможные варианты нашей структуры. => можно не писать тесты.
Нельзя. Так как вы не знаете насколько правильно она работает ваша логика. Вам все равно надо написать тесты на __логику__, и если это качественные тесты, то они покроют и отсутствие поля.
Зачем? В чем сложность?
Потому что
разобьем этот модуль на 4 отдельных
у вот этих двух структур полностью изменим представление
поменяем внешний интерфейс у библиотеки
Это з __логически__ разных этапа.
Я говорю, что с типизацией это проще.
Та не проще, просто «по другому». Вполне возможно «непривычно конкретно вам», но тут дело не столько в просто/сложно, сколько умеете (и насколько хорошо) ли вы работать в конкретном стиле, или же вы работаете в другом стиле.
Практически все места, которые надо подправить, автоматически найдет компилятор => я могу тратить свои силы на что-то более плодотворное.
#define TRUE FALSE //Happy debugging suckers
Надеясь на компилятор разработчик только вводит себя в заблуждение (излишне расслабляется).
1) Снова же, качественные тесты дают -такую же- значительно большую гарантию как и компилятор.
2) Тесты (на логику) писать все равно надо.
Из 1 и 2 возникает вопрос: так ли сильно типизация влияет на качество кода?

именно поэтом наверное вместе с redis-server, который написан на С, включен внушительный набор тестов.

Внушительный — это у sqlite :) (в 1000 раз больше KSLOC тестов, чем кода)

www.sqlite.org/testing.html

Я слышал на нём любят писать парсеры текста. Ещё были новости про банки, которые переходили на oCaml. У меня есть такое подозрение, что F# стал диалектом oCaml, а не Haskell, как изначально планировалось, именно по этой причине.

Да в каких угодно приложениях, на самом деле. Фирма просто финансами занимается, поэтому приложения в основном «финансовые». Ну, так уж получилось.

Да в каких угодно приложениях, на самом деле.
Тут речь не столько о возможности (существовании), а о массовости.

Массовость чего? Кол-ва контор, которые используют язык? Кол-во программ, которые на нем написали эти конторы? Кол-во кода в opensource-е? Что-то еще?

Массовость чего?
Та не важно :)
прочитайте контекст:
Lisp хороший для того, щоб його реалізовувати, а не для того, щоб на ньому щось реалізовувати. OCaml має бути набагато краще в цьому плані.
От крім emacs лісп особливо і не використовується, наскільки я бачу.

Цитрикс активно использует ocaml в xen для создания внешнего api своего гипервизора.
Вообще-то некоторые языки изучают на для того, чтобы потом «найти крутую работу за 100500 денег», а для расширения кругозора и знакомства с концепциями альтернативных подходов в реализации тех или иных задач.
Но это врядли тема для обсуждения на DOU, здесь такие суждения еритичны априори (:

Вообще-то некоторые языки изучают на для того, чтобы потом «найти крутую работу за 100500 денег», а для расширения кругозора
Так это вы начали говорить про бабло.
А про «популярность» важно другое: туллинг (как тулы для разработки, так и библиотеки).
Расширять кругозор хорошо когда видишь как с помощью того или иного подхода можно решить повседневные задачи задачи.
Если цель «знакомится с альтернативными концепциями» куда лучше Скала/Кложур/Груви, эт если джавист.
Для человека у которого питон основной, не уверен что посоветовать. Но если выбирать между Хаскелл и ОКамл, то все же Хаскелл, поскольку просто больше и живее сообщество.
Не с позиции наличия тех или иных библиотек или синтаксических особенностей
Как-то не особо стыкуется с целью расширять кругозор. Хаскелл и ОКамл довольно похожы синтаксически.

поэтому и появился этот топик, и да OCaml и Haskell все ж таки отличаются на уровне некоторых концепций

Я думаю, ви просто не пробували :) Маю досвід програмування на ліспі і рубі. Ruby після ліспа (того, що common) здався досить таки «дерев’яним». Те що в ліспі робилося просто і органічно, на рубі виходило значно заплутаніше, складніше і незрозуміліше...

Дайте вгадаю, ви пробували програмувати на ліспі на рубі?

Ну, я б сказав, не тільки пробував і не тільки з ними :)
Просто склалося, що після того, як уже десь рік працював з ліспом, треба було вивчити рубі (на роботі була така штука, як Redmine і до неї треба було дописати пару плагінів). От зразу і відчув контраст :)

Я думаю треба було звернути увагу на природні для Ruby методи і паттерни програмування і не тягнути їх з ліспа.

OCaml, а не SML (по типу Scala
Еще чисто интересно почему ты считаешь что скала ближе к СМЛ чем окамл?

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

Вам же понравился OCaml, а все эти языки в рамках одной парадигмы. Нужно учиться на том что нравится. Если будут проблемы, поменяете, не будут — будете пользоваться.

А stm как то обозначают поддержку многопоточности? Ну и школота пошла однако.

ghc ж этой моделью пользуется для конкурентного доступа к памяти, why not?

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

Ну .... с оговорками. Во-первых, lwt. Во-вторых, Async

Во-вторых, Async
Посмотрел доку, и почувствовал на минуту себя в 90-ых.

И как, все это сможет эфективно использовать 64 ядра на моем сервачке для бложека?

Підписатись на коментарі