my dumbstreaming + oleg's iteratees
May. 8th, 2011 04:24 pmУже долго прикидываю так и эдак, но не могу до конца сообразить.
Есть мой dumbstreaming -- протокол для передачи строк, который планирую расширить так, чтобы он позволял передавать не одну строку в одном пакете, а несколько строк сразу.
Конечно, я изобретаю tnetstrings, но у меня преимущество: типы известны заранее (а именно, строки), а не указываются в конце сообщения, сразу известно количество и объём каждой строки, ну и разделители помогают надёжности. Эти преимущества позволят обрабатывать всё потоковым образом.
Для этого у меня есть iteratees.
Задача парсинга разбивается явно на два слоя: 1. парсер потока, которым передаются списки строк, работа с длинами и количествами строк, разделителями -- собственно, дело библиотеки, и 2. парсер непосредственно строк, для каждой строки в теории свой итерат.
Пока единственное, что получилось, это
То есть, пользовательская функция получает количество строк в пакете и возвращает список результатов.
Ещё есть идейки позаигрывать с fold:
-- функция получает количество строк в пакете (на всякий случай), текущее значение аккумулятора и возвращает итерат, который будет применён к потоку и который возвратит следующий аккумулятор для следующей строки в пакете.
Однако, весь цимес итератов как раз состоит в замене fold для ввода-вывода. То есть, жопой чувствую, тут может получиться всё решить вложенными(?) итератами. Но как -- не могу сообразить. В общем, простой bind итератов меня бы устроил, было бы
После того, как описал, чуть-чуть прояснился вопрос (а именно, попробовать пойти так же, как из fold получились итераты первого уровня), но, всё равно, как-то непонятно.
UPD2.
"Давай по-новой, Миша, все хуйня."
первый аргумент -- пользовательская функция, на основании количества кусков, номера куска и количества байтов в куске выдающая итерат, который будет кушать байтики этого куска и возвращать значение с типом 'i. Второй аргумент -- итерат, который будет кушать значения с типом 'i и возвращать результат с типом 'a. И функция read родит итерат, который применяем к потоку байтов и имеем результат с типом 'a.
Почему преобразование 'i -> 'a и почему не возврат list 'i? Потому что это простым образом делается из текущей схемы, передавая стандартный итерат stream2list, который как раз iteratee 'i (list 'i).
Есть мой dumbstreaming -- протокол для передачи строк, который планирую расширить так, чтобы он позволял передавать не одну строку в одном пакете, а несколько строк сразу.
Конечно, я изобретаю tnetstrings, но у меня преимущество: типы известны заранее (а именно, строки), а не указываются в конце сообщения, сразу известно количество и объём каждой строки, ну и разделители помогают надёжности. Эти преимущества позволят обрабатывать всё потоковым образом.
Для этого у меня есть iteratees.
Задача парсинга разбивается явно на два слоя: 1. парсер потока, которым передаются списки строк, работа с длинами и количествами строк, разделителями -- собственно, дело библиотеки, и 2. парсер непосредственно строк, для каждой строки в теории свой итерат.
Пока единственное, что получилось, это
value read : (stringscount:int -> list (iteratee char 'a)) -> iteratee char (list 'a)
То есть, пользовательская функция получает количество строк в пакете и возвращает список результатов.
Ещё есть идейки позаигрывать с fold:
value read : (stringscount:int -> 'a -> iteratee char 'a) -> 'a -> iteratee char 'a
-- функция получает количество строк в пакете (на всякий случай), текущее значение аккумулятора и возвращает итерат, который будет применён к потоку и который возвратит следующий аккумулятор для следующей строки в пакете.
Однако, весь цимес итератов как раз состоит в замене fold для ввода-вывода. То есть, жопой чувствую, тут может получиться всё решить вложенными(?) итератами. Но как -- не могу сообразить. В общем, простой bind итератов меня бы устроил, было бы
(it1 >>= fun v1 -> it2 >>= fun v2 -> return v1 + v2)
, но фишка в том, что it1 и it2 должны не трогать поток за пределами того, что им выделено, то есть, если в терминах итератов, должно было бы быть что-то типа ((join & take len1 it1) >>= fun v1 -> (join & take len2 it2) >>= fun v2 -> return v1 + v2)
, и не представляю, как это сделать.После того, как описал, чуть-чуть прояснился вопрос (а именно, попробовать пойти так же, как из fold получились итераты первого уровня), но, всё равно, как-то непонятно.
UPD2.
"Давай по-новой, Миша, все хуйня."
value read : (ntotal -> npart -> nbytes -> iteratee char 'i)
-> iteratee 'i 'a
-> iteratee char 'a
первый аргумент -- пользовательская функция, на основании количества кусков, номера куска и количества байтов в куске выдающая итерат, который будет кушать байтики этого куска и возвращать значение с типом 'i. Второй аргумент -- итерат, который будет кушать значения с типом 'i и возвращать результат с типом 'a. И функция read родит итерат, который применяем к потоку байтов и имеем результат с типом 'a.
Почему преобразование 'i -> 'a и почему не возврат list 'i? Потому что это простым образом делается из текущей схемы, передавая стандартный итерат stream2list, который как раз iteratee 'i (list 'i).