← All posts tagged Haskell

SannySanoff

А вот в Хаскеле partial application убогий:

f x y z = x + y * z;

а хочешь частично применить только x и z — и болт: изгаляйся. f1 x z y = f x y z; q = f 10 3; q 2

В kdb+ веселуха,

f:{[x;y;z]x+y*z} — определение ф-ии
var1:f[10;;3] — частичное применение, параметры разделяются ";".
(Ну а если последние параметры надо оставить висяком, то и точки с запятыми тоже не нужны).
var1[1] — дает 13
var1[2] — дает 16

короче, пока я не узнал, все ломал голову, где же функция flip.

А вот на тебе, на лопате, не подавись!

SannySanoff

Закинул удочку в Serokell, которые вроде б то под руководством Дарта Вейдера^W^WPhilip Wadler пишут свой альткойн на Хаскеле. Питерские, но ищут remote чуваков.

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

Говорят, что работы на 8-9 часов, прислали небольшую заготовку, которая по юникс сокетам коммуницирует, API неможко парсит, таймауты там тестовые имплементит, которые нужны по ТЗ, молодцы.

Бросаться в это? Кто пропустил и хочет, могу зафорвардить, они раскидали тем, кто выразил интерес в середине декабря.

SannySanoff

Вот я написал я в продакшн на Хаскеле концентратор вебсокетов, который, значит, держит 30-40к соединений на ядро, и там еще роутящая логика, включая парсинг protocol buffers, небольшое кеширование, кафку и проч. Меня устраивает все, кроме того, что

1) я, как не знающий хаскеля, пишу код медленно и путанный, и 2К строк в уже утомительно педалятся (mental burden без нормального ide, плюс без отладчика писать это другой мир, другой образ мысли). Кстати,

$ cat *.hs| grep -v '^$'| wc
1950 10104 102376

получается 102376/1950=52 символа на непустую строку. Ревью кода я скромно не прошу, но жуечных хаcкелистов прошу померять их метрики. У меня есть надежда, что я вдруг просто не тупой, а лишь не угадываю каких-то очевидных для многих остальных людей нюансов.

2) Atom регулярно тормозит по 40 секунд, перечитывая общение с ghc-mod, в Atom-helper (процесс) регулярно 100% CPU time: парсит выхлоп наверное.

А Хаскель я выбрал потому что
1) перфоманс
2) легковесные треды для io и можно писать как будто блокирующие вызовы, проще писать все алгоритмы.

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

Ерланг? Перфоманс протобуф парсинга меня немного беспокоит, а так вроде должно быть ОК.

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

Жаба? Отсутствие легковесных тредов, но так вроде все остальное (опыт) компенсировало бы это.

Раст — отсутствует норм асинх ИО, а так смысла нет.

C/C++ — не нашел нормальных async i/o вебсокет библиотек (пробовал пару в самом начале проекта, даже чтото работало, но не всегда: в обоих были нюансы вплоть до неработы), не говоря уже о отсутствии легковесных тредов (зная С++ шников, наверняка у них ответы есть на все, потому данное заявление прошу не считать категорическим)

Ноде, кроме того что хипстота, тормозит (это тоже хипстота впрочем)

У кого такой же клеви RTS как у Хаскеля?

SannySanoff

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

SannySanoff

Одним из незаменимых фич IDEA для меня является история перемещений позиции курсора по файлам. В IDEA их две: можно идти в прошлое по местам изменений кода, а можно по местам, где ты был перед тем как нажал кнопку глобального перемещения (Ctrl+Home/End, перемещение в результате поиска, перемещение в результате перехода на подсвеченную ошибку итд).

Таким образом, нажав несколько раз, например, Ctrl+Alt+Left, побываем во всех местах, которые у нас в башке имеют еще горячий контекст, а нажав Ctrl+Alt+Right, в обратном порядке вернемся к текущему месту.

Существуют языки, которые по сравнению с жабкой требуют частой беготни: посмотреть на дефинишны/типы, вспомнить имя итд, то есть Хаскель. Я пробовал вспедальнуть на Leksah (под гей-осью оказалась неюзабельна), брал Atom (интеграция с ghc-mod какая-то есть, можно терпеть), Vim не пробовал, но раньше перед переходами приходилось маркировать позицию, eclipse-fp говорят, сдох, а вот для IDEA нашел intellij-haskell, которым щас и пользуюсь (подсказки не хуже чем в атоме + всякие этим стандартные ништяки).

Вот я как раз я в Атом не смог именно из-за отстутствия истории перемещений, уж очень это у меня в спинном мозгу.

А что в спинном мозгу у вас? Как в этих ваших емаксах (добавить свое) сбегать в начало файла, потом в середину, а потом вернуться в другую середину, есть такое? Или изобрели что-то иное?

SannySanoff

Короче, когда я писал нагрузчик вебсокетов чтобы тестировать концентратор вебсокетов, я писал функцию, которая (концептуально) делает следующее

fun = forever $ do
let t1 <- currentTime
WS.socketSend req
response <- WS.socketReceive
let t2 <- currentTime
recordRoundtrip (t2 — t1)
threadDelay (random * delay)

и значит нафоркал (forkIO) их немеряно. Смысл был в том, чтобы не пинговать тупо в цикле, потому что интересовало как отличается total request rate в зависимости от к-ва клиентов, редко пингующих. Вдруг миллион коннекшнов где-то участвует в формуле, и будет совсем низкий RPS.

Проблема была в том, что сервер-то хавал это к-во клиентов легко (!), а вот клиенты не генерили нагрузку от слова совсем. Ни на node.js, ни на хаскеле, тупо 10-15 тысяч запросов с ядра, с уменьшением до двух-трех тысяч с ядра, если загружать больше ядер. /proc/interrupts показывали нагрузку на xen rescheduling, и я понял что где-то туплю.

Карочи, оказалось, что шедулинг действительно тупит в хаскеле. То есть легковесные треды не жрут тяжелые системные треды, НО threadDelay ни разу не легковесен, потому что использует какой-то системный аларм (!), который не скейлится, а зря.

Короче, вставил в свою функцию (вместо задержки) последовательность takeMVar/putMVar на общую глобальную переменную, и повесил еще один тред который регулярно отнимает этот mvar на указанный промежуток времени.

Все сразу стало на свои места! Ну, ядер/процессов одновременно много, они пульсируют вразнобой, так что ок.

P.S (процессы на ядра affinity ставил, прозрел прямо).

SannySanoff

Наткнулся на конкурс Душкина по функциональному программированию. Только он уже закончился. Душкин любит Хаскель. Я тоже люблю Хаскель, но пишу щас на Q. Я считаю, что на Q тоже можно решить задачу с великолепной фефкой и ее жуками ( haskell98.blogspot.com ).

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

sx:flip select distinct state from s:`state xkey s0:flip `sn`state!("is";" ")0:`$":states.txt"
f:{([freq:(x 0)]freqi: (x 1))} flip {(`$4_x;"I"$3#x)}each read0 `$":frequencies.txt"
j:{[pc;s] {[pc;x]pc,`$x}[pc]each ", " vs s}
k:{[q]zh:first cols q;{[zh;x] j[(zh;x`v);string x`w]}[zh] each `v`w xcol 1_q}
ls:`state`wha xkey l:((flip `wha`freq`state!flip raze raze [k each {("ss";": ")0:`$(":",x)}each system "ls *.dat"])ij f) ij s
fres:{exec(`$"-")^freq from(`state`wha xkey flip((enlist`wha)!(enlist(count s)#x)),flip s0)lj ls}
t1:flip sx,raze{(enlist x)!enlist(fres x)}each exec distinct wha from l
`:t1.csv 0: {ssr[x;",";";"]} each csv 0:t1 / write csv
select count i by state from l / count species
select sum(freqi * sn) by wha from l / calculate extinction

Базу данных KDB, на которой пишут на Q, можно скачать по адресу kx.com.
KDB поддерживает многопоточную обработку данных, индексы и терабайтные партиционированные базы данных (любит RAID), распределенные вычисления (remote KDB calls), содержит встроенный http сервер, умеет в json и XML, умеет умножать матрицы и всяко их джойнить, умеет time series, скользящие окна и многоступенчатые averages, умеет интерфейс к С++ для нативных функций. Еще он похож на лисп (можно конструировать и выполнять S-trees). И еще он, сцуко, очень быстрый.

Промышленная версия KDB поставляется в виде бинарника размером в 417792 байта (.exe для win32, к примеру):

Directory of C:\q\w32

11/25/2014 11:12 AM <DIR> .
11/25/2014 11:12 AM <DIR> ..
11/18/2014 10:51 AM 417,792 q.exe
1 File(s) 417,792 bytes

Вместе с ним идет реализация языка Q на языке K, 19231 байтов (этот ад я даже не хочу здесь затрагивать):

Directory of C:\q

11/18/2014 10:51 AM 19,231 q.k

И те, кто любят иногда упороться, упарываются им до бесконечности.

SannySanoff

Понадобилось постпроцессить некие типовые сгенеренные по-местному PDFы на IOS-е: слегка распарсить, и добавить несколько аннотаций (PDF аннотаций), потому что нативный местный Quartz не умеет аннотаций.

Чем это сделать? Решил взять Хаскель, наклепать разборщик и сборщик PDF-а, без особой детализации.

Скачал по этому случаю EclipseFP (хаскель под эклипс). И что бы вы думали? Оно таки работает, и даже достаточно приятно, и даже фичастее чем Leksah (да упокоится оно с миром). Но по исходникам местных установленных пакетов все равно не лазит, хотя типы выводит и подсказывает. И даже с локальными перемененными ок. Я рад, я весьма рад! Осталось только будет бинарнег собрать под IOS, допишу, буду кросс-компилировать.

Три любопытные мне кровоточащие технологии в одной маленькой задаче (хаскель, eclipsefp, cross-compilation). Ужос, аж трепещу.

SannySanoff

На последнем ICFPC нужно было писать AI (алгоритм) для бота PACMAN на функциональном языке, неважно каком, потому что то, на чём пишешь, нужно было затем скомпилировать в байткод лисп-машины. Было выбрано нехилое подмножество Java, был написан компилятор в нужный байткод и затем писался AI уже на Java, с женериками, функцией fold0, filter, лямбдами и подобной радостью.

Это был тот редкий момент, когда на жабе пишешь purely функционально.

И у меня оформилась, наконец, общая претензия к функциональному стилю.

Функциональный стиль заставляет придумывать множество идентификаторов или в противном случае писать многоэтажные выражения. Если писать функции — одно-пятистрочники, то это будут идентификаторы функций. А если писать функции 20-строчники, это это идентификаторы let-varibles или их аналогов. А если ты пишешь многоэтажные выражения, то не отладить нормально: не посмотреть в процессе промежуточные состояния.

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

Да, я на обычной индустриальной жабе пишу функции на 3 экрана, бывает. Один FOR, за ним другой WHILE, комментарии над каждым. А когда не пишу большие ф-ии, то у меня короткие типовые имена методов в пространстве имен конкретного класса.

И кстати да, в нашей функциональной жабе работает autocomplete с привязкой к типам и женерикам (правда часто со скрипом!), и я почувствовал каково оно было бы на Хаскеле писать в нормальной IDE. Круто было бы на Хаскеле с нормальной IDE. Но проблема придумывания и вспоминания названий всё равно бы осталась.

Это наверное возрастное (?).

Всё остальное в функциональном стиле для меня хорошо. И немутабельность хороша, и чистота и грязнота. Ну а конкретно в функциональной жабе несколько напрягает разрастание сигнатур типов, естественно 8), даже в восьмерке, долгих ей лет. И еще неприятно прикалывает ошибка типа, на которую показывает IDEA, в третьем параметре какой-то функции которую я вызываю внутри лямбды внутри map, а всё потому что результат этого map присваивается переменной, тип которой уже написан слева и не сходится с результатом выражения справа. Я бы предпочитал чтобы IDEA ругалась, наоборот, только на тип переменной слева от знака присваивания (binding, whatever), если правая часть имеет осмысленный тип. Но может на правой части просто можно ругаться для них разнообразнее? Кто знает.

Ну, и ICFPC в этом году мы продули: писать AI для ботов клеточных игр никто достаточно хорошо не умеет, и особо не любит, не то что компиляторы или профайлеры результирующего кода.

SannySanoff

Вот FPComplete таинственно размахивало обещанием заструячить офигенный Haskell IDE и потрясти основания основ программинга на Хаскеле. Лично я грыз ногти — будет ли это еще один eclipse-based подход или они осознали IntelliJ IDEA и наконец-то напишут туда плагин в тамошнем духе?

Реальность ( youtube.com ) оказалась куда реальнее. Перцы написали web-based редактор с сервер-сайд GHC фермой и github integration. Ну йолы палы!

Как я буду тестировать мои бинарники, скармливая им на stdin локальные файлы?
Как я буду грепать мои логи?
Как я буду кабалить свои кабалы?
Где мои брекпойнты? Где мой evaluate in context? Где мой рефакторинг?

Где мой 21 век?

Какая-то мода на программирование в бровзерах на планшетах без клавиатуры в гамаке стоя на лыжах — вот нынешний тренд ( touchdevelop.com , между прочим рекомендуется для ознакомления, чуваки реально потрудились; нашел по ссылкам от нынешних организаторов icfpc 2013 ( research.microsoft.com ) . Кто проникся Scratch ( scratch.mit.edu ) тому понравится ) . Нынче серьезные инструменты делает токо МС и IntelliJ, остальные используют продвинутые текстовые редакторы (и это всё же лучше чем web-based IDE!)

Игра в баловство сразила даже на нашу священную корову Хаскель, слава богу не сам SPJ умом тронулся, а другие, хотя и весьма индустриальные и весомые, хаскель-дяди.

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

Пока писал, увидел что игра у других людей что-то тоже не клеится — #2433791 . Шиза косит ряды людей.

SannySanoff

Что меня всегда умиляет, так это что любая лекция по какому-то аспекту хаскеля (например: монады, high performance или там веб какой), обязательно на одну треть состоит из описания самого хаскеля с самого начала.

Типа есть такие люди, которые не знали, но из одной лекции сразу поймут и что такое хаскель, и как на нем делать параллельный многопроцессорный обход дерева, и бенефиты foldl' супротив foldl. В голову приходят только математики-теоретики, вышедшие по какой-то причине из спячки как раз накануне этой лекции.

Я понимаю, что это стандартный формат научных papers, но ведь ёлы палы, у меня закончились носовые платки!

навеяно этим: slideshare.net

SannySanoff

На реддите обсуждение новой фишки "holes", которая появится в GHC ( reddit.com ). Я сам не знал что это такое. А это вот что:

В любом месте, где можно писать undefined (а это почти везде), ты пишешь прочерк (_), и компилятор тебе дает warning, с указанием типа, который туда просится, и даже еще из local scope предлагает несколько bindings по типу подходящих, с именами!

Брателлос сидящие на реддите — одна половина другой объясняет что это такая фишка для девелопмента, и что в продакшн она не попадает.

И никто из них не сказал, что это ж реализация autocompletion (комплишн) которой место в IDE! Там, на конце галактики, авторы услышали мои чаяния и претензии к хаскелю, шо там автокомплишн сделать надо очень стараться, и реализовали это по своему, академически, но полезным образом. Ну малаццы!

SannySanoff

По результатам #1824146 открыл для себя haskell binding for judy.

Judy — реализация sparse table в виде недецки хитрого дерева. Подходит для маппинга Word64 -> Word64, то есть для хешей с ключом Word64.

Афтары биндинга к хаскелю рекомендуют на крайний случай юзать StablePtr, чтобы кидать туда любые данные в качестве значений.

А вся радость указанного judy for haskell в том, что само дерево растет в сишной куче и не напрягает хаскельный GC на больших объемах. А это, для тех кто ценит, очень замечательно.

Описание алгоритма доставляет кроме самого алгоритма еще методикой его оценки, который у авторов выходит по производительности круче теоретического предела, потому что они на самом деле оптимизируют алгоритм для более эффективного использования процессорного кэша, и очень этим гордятся. judy.sourceforge.net

Молодцы!