Про HaTeX 3 и юникод в коде
(репост из tumblr)
Вступление
Давненько я не заглядывал сюда и не писал ничего содержательного. Но тут в очередной раз есть повод поделиться впечатлениями от новых интересных знаний и к тому же для этого удалось выкроить немного времени.
Итак, я дождался таки выхода в свет 3й версии библиотеки HaTeX - предыдущая версия была аж год назад. И за этот год я периодически писал автору, интересуясь, не собирается ли он что-нибудь делать, поскольку предыдущая версия была хороша только как концепт, но слишком далека от идеала и малопригодна для реального применения (хотя я ей всё таки пользовался и надеюсь ещё отдельно рассказать как именно). Хотел даже сам переделать её, но как всегда не хватало времени.
Я кстати писал в мае о том как и почему мне нравится HaTeX. Так вот пред-релизное известие о новых концепциях в HaTeX-3 очень меня обрадовало. Главный момент (для меня), в том, что теперь есть специальный алгебраический тип LaTeX
, с помощью которого конструируются LaTeX-выражения на Haskell’е. Такой подход даёт возможность контролировать валидность получаемых (true-)LaTeX-выражений на выходе.
На самом деле это тоже не то, что я хотел, когда говорил о типо-безопасном LaTeX’е, но всё же, лучше, чем было раньше. Я вижу это скорее как класс типов, которые можно представить в форме LaTeX’а, но об этом надо ещё подумать (это мне напомнило цитату, по ходу дела).
Немного об изменениях
Ладно, ближе к делу. Когда я пользовался HaTeX’ом до 3й версии, я написал для себя небольшое дополнение - там были команды, которых мне не хватало и удобные сокращения. Так вот перед тем как начать пользоваться новой версией, я естественно занялся переделкой этих дополнений для совместимости с ней. На самом деле менять почти ничего не пришлось - в основном только уродские сигнатуры типа foo :: Monad m => LaTeX m
заменились на foo :: LaTeX
, что конечно же к лучшему.
Насчёт пропажи (а на самом деле опциональности) монад в новом HaTeX стоит прочитать пост автора о двух стилях. Он говорит что новый способ, изобилующий операторами <>
для склейки частей LaTeX
-выражений не шибко приятен для глаза (“Yes, all these operators seem ugly”), но мне это наоборот больше нравится “) Просто я и в старой версии не всегда пользовался do
-нотацией (по формуле/фразе на строчку?), а частенько писал что-то типа (от балды что-то напишу сейчас)
1
|
|
Что на обычном LaTeX’е означает примерно следующее:
1
|
|
Что может быть выглядит короче, но уж на мой вкус совершенно отвратительно. А в HaTeX3 это запишется так:
1
|
|
Во-первых так по-моему лучше (читабельнее), а во вторых, поскольку я пользуюсь conceal-фишкой в Vim’е, то у меня в нормальном режиме >>
заменяется на симпатичную кавычку »
(то есть одним символом), а для нового оператора я сделал замену <>
на ◇
(юникодовский символ “white diamond”).
И это по-моему прекрасно, потому что код выглядит чисто и чудесно и без всяких там “ugly operators”.
Vim conceal
Про использование юникодовских символов стоит сказать отдельно. Я не очень люблю conceal в Vim’е, потому что меня раздражает то, что в нормальном режиме всё сворачивается в один символ, но при перемещении он воспринимается как свёрнутая последовательность символов, то есть я тупо натыкаюсь на такой символ, жму вправо 10 раз, а курсор не реагирует. Естественно это приводит к проблемам при копировании/вырезании и т.п. Не понимаю, почему так сделано.
Поэтому conceal’у я оставляю маленькие визуальные украшательства, такие как замена <>
на ◇
или
1
|
|
на
1
|
|
^__^
Юникодовские символы для операторов
В остальном же, я использую юникод для операторов в Haskell’е, благо GHC это поддерживает уже давным давно (можно хоть по-русски функции и типы называть).
Я думаю, любой правовер годный редактор позволяет ненапряжно писать, используя юникодовские символы. В Vim’е я делаю это используя функцию IMAP из плагина LaTeX-Suite. Аналогичное можно сделать тысячей других способов и уж точно можно сделать в Emacs/Textmate/Vico. Итак, я пишу в .vimrc
cледующую строчку:
call IMAP (";<" , "≤" , "haskell")
И теперь, при наборе кода;,
моментально заменяется на ≤
- это как ввод иероглифов по их фонетическому эквиваленту (пиньинь вроде называется).
;
я использую как префикс, чтобы отличить этот иероглиф (макрос? “/) от обычного ввода символов, поскольку ;
не используется в Haskell’е (нет, не используется).
Теперь вернёмся к моим дополнениям HaTeX’а, которые я кстати назвал HaTeXExtension. Не шибко хорошее название, но другого пока нет. Я определяю там много таких юникодных операторов:
1
|
|
Согласитесь, выражение слева от знака равно выглядит приятнее, чем то, что справа. Поэтому и пример кода, данный вначале будет выглядеть иначе (повторяю для наглядного сравнения). Было:
1
|
|
Станет:
1
|
|
А при переходе в нормальный режим с conceal’ом, так и вообще
1
|
|
Что выглядит уже не длиннее чем LaTeX’овский вариант, и намного симпатичнее его. Более того, эта запись совсем немного отличается от математической записи (если не брать во внимание “двумерность” математического синтаксиса). Для ясности, дам определения этих операторов:
1 2 |
|
(другое имя потому что in
- ключевое слово в Haskell)
1 2 3 |
|
тут ¸ - это такая красивая арабская загогулинка, похожая на запятую, которую возможно тут особо не разглядишь, но которая у меня в Vim’е с правильным шрифтом отлично смотрится “)
Ну и последний оператор - это как бы “применение функции к аргументам”, чтобы писать f.:(x + y)
а не f <> "(" <> x + y <> ")"
или f <> prn (x+y)
(где prn
просто окружает аргумент скобочными символами):
1 2 3 |
|
Заключение
Разумеется всё это можно обоснованно покритиковать на тему того, что не всегда удобно набирать эти юникодовские символы и что вообще это никому не нужно, заменять двух-символьный оператор односимвольным, или это можно сделать через conceal чтобы добиться просто визуального эффекта.
Но ящитаю, что это наоборот очень правильно и важно - код должен выглядеть чисто и однородно. И на мой взгляд, эти символы, сокращающие код и зачастую приближающие его к естественной/общепринятой математической нотации, намного меньше нарушают его однородность и прозрачность, чем всякие служебные символы типа слеша в LaTeX’е и этих ужасных фигурных скобочек. И вообще, по-моему нужно расширять синтаксис обычных языков программирования подобным образом - юникод уже никого ведь не удивляет, а если ещё и двумерный синтаксис сделать (как во всяких maple’ах)?….
P.S. Завтра постараюсь написать пост про то, как я использую Template Haskell в своём HaTeXExtension чтобы “скрэпать свой бойлерплэйт-код” (: И да, выложу код на гитхаб.