dastapov: (Default)
[personal profile] dastapov
На своей нынешней работе я много пишу на OCaml. Не только на нем, но если это не SQL, и не простенькие скрипты, то это почти наверняка будет OCaml. И по результатам трех месяцев я решил сесть и записать свои негативные впечатления от, скажем так, перехода с Haskell. Про позитив писать особого смысла нет - ну, почитаете вы его, покиваете головой и все. А так, глядишь, кто чего посоветует :)

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

1 Сигнатуры типов
1.1)Сигнатуры в .ml

В Haskell можно было легко и просто написать у любой функции сигнатуру прямо рядом с реализацией:
foo :: String -> Int -> IO ()
foo = bar . baz

В OCaml же такое счастье недоступно. Можно, конечно, извратится:
module type Foo : sig
val foo : string -> int -> ()
end = struct
let foo = ..
end
include Foo

Но это же как-то противоестественно. Хорошо, если функция определена не через частичное применение других функций - тогда можно явно указать типы аргументов:
let foo (x:string) (y:int) = ...

А иначе - счастья нет :( Или есть, но я про него не знаю?

1.2)Сигнатуры у top-level определений.
В Haskell считалось хорошим тоном писать у всех экспортируемых определений типы, чтобы код было проще читать. В OCaml интерфейс вынесен отдельно (в .mli или module type ... : sig) и можно бы сказать, что типы описаны там. Но! Когда читаешь чужой код в .ml, хочется иметь перед глазами типы, а не держать в соседнем окошке .mli и поглядывать туда. Частично ситуацию спасает ocamlspot и интерфейс к нему из emacs - можно поставить курсор на нужное место, нажать C-c C-y и увидеть тип выражения, но это резко снижает скорость чтения кода.

А еще в haskell был хороший режим "ругаться на top-level определения без сигнатур". И компилятор в этом случае говорил: "вот у вас тут foo без типа, это нехорошо. У меня получился тип вот такой: ...".  Это было хорошо и удобно, и без этого как-то плоховато.

2 Импорт определений из других модулей
В OCaml модуль импортируется целиком - "open Module.Name" и получите и распишитесь все определения из Module.Name. В Haskell можно было указать список импортируемых в текущую область видимости функций, и это, опять же, сильно помогало читать чужой код.

А еще можно было попросить GHC выписать свое видение списка импортов для всех компилируемых модулей, с четким перечислением того, что откуда реально импортировалось. Временами этого сильно не хватает.

3 Компиляция
3.1) Я не скажу за всю Одессу, и, например, за godi, но я таки скажу за omake.
OMake - это такой make, который умеет много чего, и в частности умеет "автомагически" находить окамловые зависимости. И это работает, и обычно работает неплохо. Но! OMake любит пересобрать зависимости "с запасом". Причем начать пересобирать их издалека. И это, граждане, временами сильно напрягает. А все из-за следующего пункта

3.2)По одному сообщению об ошибках в руки
Возможно, я тормоз, и не дочитал документацию на omake, но в моей практике компилятор выдает мне одно сообщение об ошибке и говорит: "ну все, я так дальше не играю. Чини вот это, и пробуй еще раз". В результате вместо того, чтобы при рефакторинге один раз попробовать откомпилировать, N раз нажать "next error", поправить кучу мест сразу и все собрать, приходится N раз делать "compile - next error - edit - смыть - повторить".

3.3)Сообщения об ошибках
Сообщения об ошибках - это почти всегда "пичалька"
а)"Error: This expression has type foo but is here used with type foo". Происходит это из-за перекрытия определения более поздним (shadowing) и выбивает из колеи только в первый раз, но все равно - горсть нервных клеток оно у меня забрало :)
b)Когда типы в реализации модуля не совпадают с интерфейсом, компилятор считает своим долгов вывалить в сообщение об ошибке весь интерфейс модуля, сколько его ни есть
c)Еще очень бодрит, когда компилятор в сообщении об ошибке цитирует грамматику языка, типа: Error("[fun_def] expected after [simple_patt] (in [expr])"). Сразу становится понятно, что не так, и что делать :)

4 Синтаксис
4.1)Ну, про вложенные match и точки с запятой не писал только ленивый. Я ленивый, поэтому повторятся не буду.

А напишу я лучше про ... комментарии.

Если так случилось, что ваши исходники собираются с помощью caml4p, и у вас только что случился merge conflict при обновлении исходников из репозитория, но по счастливой случайности он случился только в тексте комментариев - рано радоваться. Если вы решили сначала устранить все ошибки в исходниках, а потом разобраться с комментариями, как это попытался сделать я, то вас может ожидать неприятный сюрприз: caml4p будет возбуждаться на "<<<<<" и ">>>>>>" в тексте комментариев и в результате совершенно правильный код не будет собираться с совершенно невнятными ошибками.

Это, право слово, был удар ниже пояса :)

4.2)[REDACTED]

4.3)Синтаксического сахара для монад в языке нет. Но так как монады удобны, их используют. В результате имеем кучу boilerplate кода для monadic binds, из-за которого, опять же, тяжело читать код.

4.4)Читать типы справа налево - это иезуитство, и меня до сих пор временами клинит. Предложение о том, чтобы писать их слева направо запихнули в совершенно упадочный по своей сути Revised Syntax, где благополучно и похоронили.

4 Функторы
Функторы - это круто, но если интерфейс к твоему коду - это функтор (смотрим на Set, Hashtbl и проч. из Core), то единственный способ написать свою функцию, которая будет работать с любым Set-ом -- это нагородить поверх еще один функтор. В резлутьтате получается "ехал функтор через функтор, видит функтор - функтор(функтор), сунул функтор функтор в функтор - функтор функтор функтор функтор!".

5 Монады

В ru_lambda я это выносить не буду, т.к. это, по большому счету, детский сад и нытье.

На самом же деле:

(no subject)

Date: 2011-07-11 11:27 pm (UTC)
From: [identity profile] maykov.livejournal.com
Не знал, что где-то по-серьезному используют OCaml. У нас на работе был/есть один француз, он даже собирался уходить, потому что ему не разрешали писать на нем. Пришлось разрешить :)

(no subject)

Date: 2011-07-12 07:50 pm (UTC)
From: [identity profile] sergey doroshenko (from livejournal.com)
Если я правильно подозреваю, про кого это @maykov, то нет, не ушел, живет, здравствует и занимается статическим анализом кодобазы.

(no subject)

Date: 2011-07-11 11:44 pm (UTC)
From: [identity profile] thesz.livejournal.com
Собираешься ли ты двигать Хаскель? ;)

(no subject)

Date: 2011-07-12 05:39 am (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Для этого надо сначала иметь точку опоры и какой-то вес.

Точку опоры в виде паралеллизма я вижу. Осталось набрать вес :)

(no subject)

Date: 2011-09-13 06:23 am (UTC)
From: [identity profile] gvy.livejournal.com
Мнэээ... параллелизм, говоришь? ;)

(no subject)

Date: 2011-07-12 03:31 am (UTC)
From: [identity profile] dmzlj.livejournal.com
А как угораздило? И, особенно интересно, в чем позитив? Я не просто покиваю, я просто наоборот с окамла съехал, поэтому в чем там был позитив, очень интересно
Edited Date: 2011-07-12 03:31 am (UTC)

(no subject)

Date: 2011-07-12 05:41 am (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Пошел работать в Jane Street, а там на нем пишут :)

Позитив в том, что это, по меткому выражению [livejournal.com profile] lionet такой себе С среди функциональных языков - все просто, понятно, местами неудобно.

Но это все равно ФП и строгая типизация, поэтому (как по мне) сильно лучше большого числа альтернатив.

(no subject)

Date: 2011-07-12 07:44 am (UTC)
From: [identity profile] nivanych.livejournal.com
А как же джава!
Там тоже строгая типизация и возможность писать в функциональном стиле!
Все эти новые языки — баловство одно!
А пишут, всё равно, на общепризнанных!
;-)

(no subject)

Date: 2011-07-12 10:29 am (UTC)
From: [identity profile] nealar.livejournal.com
Напиши мне на ней map

(no subject)

Date: 2011-07-12 10:49 am (UTC)
From: [identity profile] nivanych.livejournal.com
;-) Злой ты какой!
Ну, можно некое подобие, вроде.
Но это будет длиннее map func lst ;-)

(no subject)

Date: 2011-07-12 10:54 am (UTC)
From: [identity profile] nealar.livejournal.com
Родного мапа там нет, а сбоку прикрутить по-человечески невозможно.
Так что, нельзя на ней в функциональном стиле.

(no subject)

Date: 2011-07-12 11:02 am (UTC)
From: [identity profile] nivanych.livejournal.com
Надо спросить [livejournal.com profile] ivan_ghandhi.
Наверняка, он не только знает, как можно исполнить в джаве что-то типа функционального стиля, но и как выдать его за человеческий ;-)
А ещё есть Scala. Вишьчо, это смотря, с чем сравнивать.
Если с хацкелем сравнивать, то не получится выдать за человечский стиль ;-)

(no subject)

Date: 2011-07-14 11:39 am (UTC)
From: [identity profile] sorhed.livejournal.com
Да ладно, тоже мне бином ньютона. Даже без многоуважаемого [livejournal.com profile] ivan_ghandhi я ещё в незапамятные времена писал на джаве очень похожие на настоящие монады (даже ещё не зная, что это монады), и успешно ими пользовался.

(no subject)

Date: 2011-07-13 10:53 am (UTC)
From: [identity profile] klapaucius-the-constructor.blogspot.com (from livejournal.com)
Вы так говорите, как будто на ocaml можно map написать (не что-то вроде мапа, а чтоб свойство map f . map g = map (f . g) выполнялось)

(no subject)

Date: 2011-07-14 11:36 am (UTC)
From: [identity profile] sorhed.livejournal.com
Не вопрос, кстати.
interface Function1<X, Y> {
    X apply(argument: Y);
}

public Collection<Y> map(Function1<X, Y> function, Collection<X> source) {
    ...
}

Как-то так должно быть.

(no subject)

Date: 2011-07-12 11:31 am (UTC)
From: (Anonymous)
> С среди функциональных языков

И что, предполагается, что это что-то хорошее?

(no subject)

Date: 2011-07-12 08:40 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Хорошее - оно в следующей фразе.

(no subject)

Date: 2011-07-13 06:55 pm (UTC)
From: [identity profile] fukanchik.livejournal.com
Ты работаешь в 10 минутах пешком от меня. Может пообедаем завтра или в пятницу вместе?

(no subject)

Date: 2011-07-13 10:17 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Предлагаю в пт или на сл. неделе скромно по пиву после работы?

Контакты - в профайле (например, email), предлагаю перемещаться туда.

(no subject)

Date: 2011-07-15 06:17 am (UTC)
From: [identity profile] b-al-u.livejournal.com
А Хаскелл - С++?

(no subject)

Date: 2011-07-12 08:57 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
А если серьезнее, то есть хорошие места в toolchain-е.

Тот же ocamlspot+emacs/vim (ткнул курсоров с терм, получил тип или перешел на определение)

Или omake -p (при этом omake будет мониторить файлы и пересобирать все, что надо, при их изменении автоматически).

(в скобках - это для тех, кто не в курсе, но кому интересно)

(no subject)

Date: 2011-07-12 04:06 am (UTC)
From: [identity profile] polosatik.livejournal.com
4. !!! :)

(no subject)

Date: 2011-07-12 04:21 am (UTC)
From: [identity profile] n0mad-0.livejournal.com
окамлогипножаба клёвая!

(no subject)

Date: 2011-07-12 06:27 am (UTC)
From: [identity profile] zeux.livejournal.com
4.4 это про 'T array option?

Можно раскрыть 4.2? Я не очень понял, что имелось в виду (в сравнении с Хаскелем).

(no subject)

Date: 2011-07-12 08:47 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
4.4 - ага. Или про string list option. Или более длинные цепочки.

4.2 - это косяк поста :) Я тут думал описать одну конкретную проблему, с которой я боролся, и пока я ее усушивал до обобщенного описания, оказалось, что описывать вобщем-то и нечего. А фраза-placeholder осталась и пошла в финальный пост :(

Ну-ка я ее вырежу.

(no subject)

Date: 2011-07-12 07:03 am (UTC)
From: [identity profile] little-arhat.livejournal.com
"""4.3)Синтаксического сахара для монад в языке нет. Но так как монады удобны, их используют. В результате имеем кучу boilerplate кода для monadic binds, из-за которого, опять же, тяжело читать код."""
есть всякое такое: http://www.cas.mcmaster.ca/~carette/pa_monad/

(no subject)

Date: 2011-07-12 08:49 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Расширения на caml4p плохи тем, что ошибки caml4p - это не ошибки компилятора, через них хуже продираться.

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

(no subject)

Date: 2011-07-12 07:20 am (UTC)
From: [identity profile] gds.livejournal.com
1.1. по крайней мере в revised syntax есть
value (foo : string -> int -> unit) s i = ...;


1.2. да, или бегать ml<->mli, или прописывать сигнатуры типов явно. Неудобно. В случаях, когда тип неочевиден, я прописываю сигнатуры в ml.

2. проще "module N = Module.Name" и далее "N.foo". Если же именно импортировать несколько функций, то
module Q = struct
open Module.Name
let foo = foo
let bar = bar
end
include Q

При желании можно написать синтаксическое расширение, но лично мне такой фокус был не особо нужен -- обычно либо open, либо N.foo.

3.3.а. Поправили в самых новых версиях, тип foo будет кое-как отличаться. Не помню, как именно.

4.1. рекомендую использовать revised syntax, он исправляет вложенные match. Про "<<" -- есть опция вида -no_quot для camlp4, отключает quotations, если они не используются реально в коде. Заодно полезно для разных "=<<" операторов.

4.2. а иначе лишаемся shadowing'а значений и вообще явного указания того, является ли вызов foo внутри функции foo вызовом себя или вызовом предыдущей foo, определённой ранее.

4.3. есть такое дело. Для частных случаев pa_monad посоветовали.

4.4. revised syntax вполне приличный, не надо грязи.

Жаба -- ок!

(no subject)

Date: 2011-07-12 08:52 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
О, 3.3.а - это круто, спасибо.

Про no_quot - тоже спасибо. Документацию надо читать :)

В 4.2.а я возмущался формой сообщения об ошибке, не более того. Shadowing нужен, тут спору нет.

(no subject)

Date: 2011-07-12 07:41 am (UTC)
From: [identity profile] johnny-the-kid.livejournal.com
Так интересно и так непонятно, какая-то исповедь алхимика!
Я все никак не доберусь до всяких там экзотических языков программирования

(no subject)

Date: 2011-07-12 08:53 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Какая ж это экзотика? Ему сто лет в обед, почитай. Вот Agda2 какая-нибудь - вот это экзотика.

(no subject)

Date: 2011-07-12 07:46 am (UTC)
From: [identity profile] sorhed.livejournal.com
Я вот тоже не понимаю, зачем он понадобился, если был всем прекрасный Standard ML.

(no subject)

Date: 2011-07-12 08:54 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Вот кстати да, могли бы взять из SML хотя бы определения функций в виде

foo _ x = ..
foo y _ = ...

:)
(deleted comment)

(no subject)

Date: 2011-07-12 08:55 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Не, я как раз писал про то, что w-t мне при всем желании рабочую визу бы не сделали. Поэтому я поехал к тем, кто сделал.

Camlp4 хорош, но у меня до него все руки не доходят.
(deleted comment)

Re: о-о

Date: 2011-07-13 10:16 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Кстати, да, собеседования были интересными - возможно стоит и написать.

Я сам отправил резюме, знакомых до приезда там не было, большинство интервью были по телефону.

Re: о-о

Date: 2011-07-25 03:40 pm (UTC)
From: [identity profile] move-yo.livejournal.com
да, расскажи про компанию если есть возможность
ребята интересные
в Германии, к сожалению, такого типа компаний практически нет

(no subject)

Date: 2011-07-12 03:29 pm (UTC)
From: [identity profile] alex-butenko.livejournal.com
:) а меня пару дней назад захантили на Orange работать, приколи.

(no subject)

Date: 2011-07-12 08:55 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
А что делать будешь?
Edited Date: 2011-07-12 08:58 pm (UTC)

Profile

dastapov: (Default)
Dmitry Astapov

May 2022

M T W T F S S
       1
2345678
9101112131415
161718 19202122
23242526272829
3031     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags