metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-03-08 10:37 pm
Entry tags:

Эпический ад

Написал таки кусок кодогенератора на F#. Сначала в лоб, просто конверсией моих типов в последовательность строк SQL запроса для создания таблиц, а потом мне резко разонравилось отсутствие разделения модели и представления и я прикрутил AST для SQL, заодно заменив выходной результат на string seq, то бишь IEnumerable<string>.
Завтра буду прикручивать AST для дельфей, если мне не откозлопитонируют мозг какой-нибудь срочно-капец-нужно-вчера хреновиной.

Теперь понимаю, чего [livejournal.com profile] zabivator устроил хаскель-срач - когда над головой не висит чистота и ленивость, но есть discriminated unions, вывод типов и это дело корректно интегрировано в привычную среду, можно особо не задумываясь писать всякий мрак.

Но при этом однозначно начинать надо с хаскеля, а для F# - еще и дотнет знать, потому что иначе этот безумный бред понять затруднительно. Хаскель лаконичен, там те же самые идеи не заслоняются синтаксисом.

[identity profile] gds.livejournal.com 2010-03-09 08:10 am (UTC)(link)
если рассматривать конкретно окамл, то проблемы с синтаксисом там есть только в случае поверхностного взгляда (на original syntax). Если же посмотреть глубже (и на revised syntax), то синтаксис служит для отражения концепций, которых нет во многих других языках (в том числе в хаскеле): полиморфные вариантные типы (те же discriminated unions, но с возможностью повторения имён конструкторов в разных типах, и с типизацией, требуемой для реализации такого), объекты (row types и их типизация; самое клёвое ооп, которое я видел), функторы (функции над модулями). Это всё очень удобно, но плата за это -- синтаксис и "порог вхождения": кому-то не нравится синтаксис, кто-то не принимает концепции (не понимают, зачем всё это нужно, ведь любой алгоритм можно накодить и без этого). Как-то так.

[identity profile] metaclass.livejournal.com 2010-03-09 08:28 am (UTC)(link)
Кстати, а как там использовать повторяющиеся имена конструкторов данных, как язык узнает, какой из конструкторов применяется?

[identity profile] gds.livejournal.com 2010-03-09 08:40 am (UTC)(link)
вот тут писал кое-что про это (чтобы не копипастить разметку). Собственно, само название типа выражения `Something не суть важно, важен лишь сам тип (а именно, какое множество значений принимает данное выражение). Например, выражение
if a=b then `A "asd" else `B 123
имеет тип
[> `A of string | `B of int ]
, этот тип инферрится и проверяется при компиляции.
Для красоты можно ввести
type mytype = [= `A of string | `B of int ]
и написать
((if a=b then `A "asd" else `B 123) : mytype)
, и типовыводилка будет знать, что выражение имеет тип mytype (например, для документирования кода или для будущего расширения вариантов и статической проверки полноты match cases). Кстати, наличие последнего -- весьма хорошая фишка окамла, которой нет и не может быть в хаскеле, она помогает писать надёжный код.

[identity profile] zamotivator.livejournal.com 2010-03-09 09:13 am (UTC)(link)
Да, возможность произвольному выражению указать тип данных офигенно рулит и бибикает.
Если выводилка типов сообщает что где-то воооооот тут какая-то страшная фигня с типами данных, то пара вручную расставленных аннотаций сильно проясняет ситуацию.
+ если мало-мальски сложный модуль, то аннотации типов функций и аргументов просто незаменимы для документирования.

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

Также офигенной фичей является опциональная мутабельность, опциональная ленивость.

По сравнению с С++ я имею HOF, могу не писать истерично (как того требует С++) типы где попало, а указывать лишь там где надо.
По сравнению с Haskell я могу делать ленивыми лишь те куски кода, которые в этом действительно нуждаются и упрощают жизнь.

В целом Ocaml - это такой локальный very pragmatic оптимум, для полного счастья не хватает лишь нормальный поддержкой венды (ocamlfind - грустно), чуть менее бардака в библиотеках (с батарейками BatList vs List - ад) - но это возможно также нужно просто научиться её готовить, да и GODI я ещё не смотрел (но для GODI - тоже самое, поддержка mingw нужна, поддержка студии (компилятора) - а то cygwin это всё не то...).

Ещё для полного счастья нужны процессы в стиле Erlang, я вот lwt смотрел - да не осилил, + собрать lwt под windows РЕЛЬНАЯ ПРОБЛЕМА.

В остальном же - идеал =)

[identity profile] gds.livejournal.com 2010-03-09 09:27 am (UTC)(link)
про аннотации для ловли ошибок типизации -- о да! Недавно решил одно ast описать чисто полиморфными вариантами (да ещё и с перекрывающимися конструкторами), так без аннотаций ловил весьма долго.

Отсутствие перегрузки по типам -- есть такое дело. Кстати, я шёл с C (до этого -- с осемблира), затем чуть поковырял C++, потом понял, что ocaml это то, что нужно, но вот тоже не хватало перегрузки. Кусал локти сначала. Потом как-то научился обходиться без неё. И только потом понял, что кое-где эмулируется вариантными типами, кое-где объектами, кое-где всякими deriving'ами.

Мутабельность и ленивость -- ок :)

Кстати, ленивость использовать так же, как в хаскеле, не стоит: например, кое-кто идиоматично пишет обработку потоков данных как функции над ленивыми списками, затем забывает голову списка в памяти и ловит ололо пыщ пыщ риальни.

Про венду -- чего там грустно с ocamlfind? У меня он работает чотко. Даже кучу других библиотек скомпилял, даже типа-дистр виндовый сделал.

GODI я тоже не смотрел, именно из-за того, что оно не умело под mingw работать в своё время.

Насчёт lwt же -- очень странно. Мой билд-скрипт для него (для довольно старого 1.1.0) состоит из "$MAKE && $MAKE install", правда вот зависимость от ocaml-ssl есть.

Процессы -- советую глянуть JoCaml, это даже интереснее ырланка (ибо типизация).

[identity profile] zamotivator.livejournal.com 2010-03-09 09:37 am (UTC)(link)
Про венду -- чего там грустно с ocamlfind?
Ой, а можно мануал, как мне получить на выходе omake + ocamlfind + ocaml + batteries? Под mingw, пожалуйста, и без cygwin!
И вообще просто шикарно - если ещё и с lwt

Насчёт lwt же -- очень странно. Мой билд-скрипт для него (для довольно старого 1.1.0) состоит из "$MAKE && $MAKE install", правда вот зависимость от ocaml-ssl есть.
Под вендовый cmd? Если под bash - то какой - cygwin или таки MSYS?

Процессы -- советую глянуть JoCaml, это даже интереснее ырланка (ибо типизация).
ВОТ ЭТО НИХУЯ СЕБЕ ПРОСТИТЕ ЗА ВЫРАЖЕНИЯ ТИПИЗИРОВАННЫЙ ERLANG ПЫЩПЫЩПЫЩ!

О дааааааа, надо заценивать, если оно годное - то срочно OTP портировать под такое щастье!!!
Edited 2010-03-09 09:39 (UTC)

(Anonymous) 2010-03-09 09:44 am (UTC)(link)
> Ой, а можно мануал, как мне получить на выходе omake + ocamlfind + ocaml + batteries? Под mingw, пожалуйста, и без cygwin!

Зачем нужен неподдерживаемый omake когда есть ocamlbuild? ocamlfind just works. ocaml бинарный с сайта - без проблем. насчёт батареек не знаю. Вообщем "у меня всё работает". Покажи конкретную проблему.

[identity profile] zamotivator.livejournal.com 2010-03-09 09:50 am (UTC)(link)
Батарейки собираются omake, и как минимум для этого omake нужен.
+ он мне больше ocamlbuild нравится.

Дальше, что значит "неподдерживаемый"? Разрабатывается аж с 2004 года, солидная история релизов и багфиксов, есть пакеты под все платформы, что с ним не так?

Ну вот я не смог собрать вместе ocaml, ocamlfind, omake под mingw так, чтобы они заработали.
Пришлось собирать всё тоже самое под cygwin, всё из сорцов.
+ вылезли грабли с camomile.
Когда попробую ещё раз попозже, и отпишусь про конкретные проблемы

[identity profile] ygrek.myopenid.com (from livejournal.com) 2010-03-09 10:06 am (UTC)(link)
Насчёт "неподдерживаемый" скорее субъективно, когда я хотел его пощупать - все ссылки на скачивание были дохлые. А omake в батарейках это какая-то диверсия, изначально оно камлобилдом собиралось, странно.

А зачем пересобирать ocaml и omake когда они в бинарниках есть? Конкретно в тулчейне проблем не должно быть, но в общем согласен - большинство камловых библиотек обычно не собираются с полпинка в каждом из портов (cygwin/mingw/msvc). Это легко понять так как кому охота всё это тестировать, а во-вторых повальная любовь к хитровывернутым bash-скриптам. Вот камлобилд тем и хорош что даёт некий общий базис и "из коробки".

[identity profile] zamotivator.livejournal.com 2010-03-09 10:41 am (UTC)(link)
А зачем пересобирать ocaml и omake когда они в бинарниках есть? Конкретно в тулчейне проблем не должно быть, но в общем согласен - большинство камловых библиотек обычно не собираются с полпинка в каждом из портов (cygwin/mingw/msvc). Это легко понять так как кому охота всё это тестировать, а во-вторых повальная любовь к хитровывернутым bash-скриптам. Вот камлобилд тем и хорош что даёт некий общий базис и "из коробки".
Как минимум, нужно чтобы ocamlfind смотрел "куда надо".
Подробно проблемы не помню, когда вернусь к этой теме - отпишусь подробней.

[identity profile] gds.livejournal.com 2010-03-09 10:10 am (UTC)(link)
проблема с omake в том, что нет официальной версии под mingw (мои патчи -- не официальная версия). Другая проблема -- багфиксы распространяются в виде патчей, у каждой ОС свои (например, в бсд багфиксы лежат в портах). Последний релиз -- 2007г, но не из-за того, что omake идеально работает -- так как работает omake не идеально, видимо есть другие причины не выпускать новые версии.
Кроме того, ocamlbuild включён в дистрибутив окамла, что означает его кошерность (его будут допиливать, так или иначе).

[identity profile] gds.livejournal.com 2010-03-09 09:50 am (UTC)(link)
под mingw+msys без cygwin -- всё есть (с omake натрахался вприсядку, вспомню -- вздрогну), но без батареек пока, ибо и мне лично не надо было, и никому из знакомых не надо было. Так-то, конечно, могу добавить и батарейки.
Но засада в том, что я вон попробовал своё оверблд на нетбуке завести, и что-то не завелось сходу (отвалилось в линковке с tcl/tk, но, чувствую, проблема глобальнее), и руки не доходили разобраться (как и сейчас не особо доходят, впрочем).
А у одного знакомого вроде как завелось замечательно, да и на локально-доступных мне компах проблем не замечал. Так что стоит попробовать, вот внешние зависимости (если не страшно, то тривиальная инструкция по сборке там рядом).

Сборку окамла падвенду осуществляю msys'овским башем.

Насчёт эрланга -- агаа :) Но там не всё так идеально, и нужно просто посмотреть, устраивает ли. А так -- оно вполне живое.

[identity profile] zamotivator.livejournal.com 2010-03-09 10:03 am (UTC)(link)
Надо бы это хозяйство всё доупаковывать, чтобы получить инсталлятор аля cygwin под венду и набор пакетов аля GODI/dpkg/apt под динукс....

[identity profile] gds.livejournal.com 2010-03-09 10:16 am (UTC)(link)
я-то из-под полы раздавал это хозяйство в виде бинарных билдов, но, так как патчу компилятор, это является нарушением лицензии. А без патченья компилятора не знаю, как завести ocamlnet/mingw, например. И смысла в том оверблде будет почти ноль.
Если бы не лицензия, всё было бы сильно проще. Сейчас это хозяйство представляет собой максимально простой способ распространять окамл и библиотеки без нарушений.

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

[identity profile] ygrek.myopenid.com (from livejournal.com) 2010-03-09 09:32 am (UTC)(link)
Что не так то с ocamlfind? Работает без вопросов.

[identity profile] nealar.livejournal.com 2010-03-09 02:57 pm (UTC)(link)
Чего не может быть в хаскеле?

[identity profile] voidex.livejournal.com 2010-03-09 04:15 pm (UTC)(link)
Аватар офигенно в тему %)

[identity profile] gds.livejournal.com 2010-03-09 08:26 pm (UTC)(link)
статической проверки того, что конкретный match будет успешно выполнен независимо от того, что ему дадут на вход. Обсуждение этого -- в каментах к посту http://ocaml.janestreet.com/?q=node/64 (что-то про undecidable говорят).

[identity profile] lionet.livejournal.com 2010-03-09 08:36 pm (UTC)(link)
Это вопрос к дефолтным сеттингам, а не к фиче, которой "которой нет и не может быть в хаскеле":

[vlm@nala:~]> ghc -fwarn-incomplete-patterns a.hs

a.hs:1:0:
    Warning: Pattern match(es) are non-exhaustive
             In the definition of `foo': Patterns not matched: Nothing
[vlm@nala:~]> cat a.hs
foo (Just x) = x + 1
main = print (foo Nothing)
[vlm@nala:~]> 


Читайте пост вместе с комментариями, что-ли.

[identity profile] gds.livejournal.com 2010-03-10 06:07 am (UTC)(link)
именно в комментариях прочитал:
But there was also some indications given that proper exhaustiveness checking in Haskell is undecidable.

Yes, they mean in the more precise sense (i.e. things that locally look partial, but are actually total because of invariants in other parts of the program).

[identity profile] lionet.livejournal.com 2010-03-10 06:36 am (UTC)(link)
Это именно что "more precise than OCaml". То есть, хотят НЕ отлавливать лишний раз ветку case:
data T = A | B | C

f A = "a"
f x = case x of
	B -> "b"
	C -> "c"
А с этим окамл тем более не справляется:
[vlm@nala:~]> cat a.ml
type t = A | B | C

let f t = match t with
	| A -> "a"
	| x -> match x with
		| B -> "b"
		| C -> "c"
[vlm@nala:~]> ocamlopt a.ml
File "a.ml", line 5, characters 8-46:
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
A
[vlm@nala:~]> 
На примитивном же уровне окамлового отлавливальщика хаскелевый работает с -Wall, нет никаких проблем:
a.hs:4:6:
    Warning: Pattern match(es) are non-exhaustive
             In a case alternative: Patterns not matched: A

[identity profile] zamotivator.livejournal.com 2010-03-10 05:47 am (UTC)(link)
Аватарка охуенна

объекты (row types и их типизация; самое клёвое ооп, которое

[identity profile] e-mmortal.livejournal.com 2010-03-15 03:03 pm (UTC)(link)
А можно про "объекты (row types и их типизация; самое клёвое ооп, которое я видел)" поподробнее?

Re: объекты (row types и их типизация; самое клёвое ооп, котор

[identity profile] gds.livejournal.com 2010-03-16 07:21 am (UTC)(link)
(решил оформить ответ в том числе в отдельном посте)

Вот тут -- Private row types: abstracting the unnamed -- описываются применения row types (и полиморфных вариантных типов заодно).
Если вкратце и своими словами, типизация объектов в окамле структурная (член структуры = метод = "row" в официальной терминологии). Обращение к члену структуры (obj#meth) заставляет тайпчекер статически гарантировать наличие у объекта obj метода meth.
Нет номинальной типизации/подтипизации объектов (по имени класса), но она легко эмулируется, если нужна.
Поля объектов могут быть как изменяемыми, так и неизменными, по желанию. Поля видны только в пределах объекта, методы видны и в пределах объекта, и за пределами. Класс может иметь типы-параметры (как обычные параметрические типы). Методы класса могут быть полиморфными (через это имеем полиморфизм второго ранга в объектах). Существует возможность создать объект или описать объектный тип, не создавая класс. Поддерживаются виртуальные методы (и статически проверяется, что любой создаваемый объект должен иметь полностью определённые методы). Поддерживается множественное наследование (хотя даже обычное наследование не часто нужно).
Одно из классных свойств ООП в окамле состоит в том, что нет нужды использовать большинство ООП-паттернов. А вот для чего можно использовать ООП, так это для эмуляции duck typing и typeclasses.