Чтобы добавлять сообщения и комментарии, .

@qnikst:
qnikst

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

@qnikst:
qnikst

зачем в кондуитах bracketP, а не bracket, или кондуиты нереально сделать MonadMask/MonadCatch?

@dr-Chaos:
dr-Chaos

Продолжая вопросы из — #2794212 . Собственно расставлением кучи ! мне удалось заставить вылетать эксепшн в нужном потоке. Однако, мне нифига не понравилась такая т.к. мне кажется это совсем не правильным. Т.е. sink по умолчанию ленивый по своим агрументам, и только после того как я сделал его энегричным, что-то заработало.
Собственно встаёт вопрос как принято решать в кондуитах проблемы с тем что санк с эксепшеном может улететь в другой поток?
Кроме того можно, же воспользоваться decodeOrFail . Но насколько я понимаю тогда придётся воспользоваться map Maybe (...) $$ catMaybe $$ sink . Но информация об ошибке пропадает. Чтоб не пропадала придётся писать свой Conduit.

@dr-Chaos:
dr-Chaos

Есть у меня RollingQueue привязанная к UDP сокету. И если в сокет записать херню вылетает эксепшн из Binary десериализатора. Но обрабатывается он совсем не там где я ожидаю. Код тут:
gist.github.com
Подскажите почему так происходит.

@dr-Chaos:
dr-Chaos

Есть у меня необходимость принимать по UDP пакеты. Выглядит сейчас это - так:
CNU.sourceSocket sock 4096  $= CL.map CNU.msgData
                                    =$= conduitDecode 
                                    =$= CL.map (uncurry EMessage)
                                    $$  CRQ.sinkRollingQueue  q

Принимается пакет, потом десериализуется, а затем суётся в очередь.
Собственно, если данные превышают размер пакета они собираются из нескольких пакетов при этом sender из UDP-шного пакета игнорируется. Тут остаётся актуальным вопрос переупорядочивания UDP-ишных пакетов, т.е. если я засуну в сокет больше 4096 с одной стороны, то на приёмнике могу получить что-то вклинившееся между этими 2-мя пакетами или это просто влияет на размер буфера? 
Сейчас появилась необходимость скомбинировать адресс/порт отправителя  с десериализованным сообщением, учитывая что сообщение может быть разбито на несколько пакетов... Хочется для этого како-то zipConduit использовать, но что-то не очень понимаю как. Собственно помогите с примером.

@dr-Chaos:
dr-Chaos

Например у меня есть некий кондуит, который получает по UDP пакеты, преобразует их в нужный мне ADT и пихает в очередь. Выглядит запуск примерно так:

void $ forkIO $ sourceSocket sock 4096 =$= ... =$= sinkRollingQueue

И вот пришло нам битое сообщение из-за него вылетает эксепшн, но я не хочу прибивать весь процесс к чертям из-за такой мелочи. Собственно первое что приходит на ум — это отловить эксепшн с пом onException, вывести в лог сообщение об ошибке и снова запустить кондуит, как-то так:

getMsg =  sourceSocket sock 4096 =$= ... =$= sinkRollingQueue

void $ forkIO $ getMsg `onException` (\e -> print e >> getMsg) 

Собственно вопрос - это обычно так и делается или я что-то упускаю?

@dr-Chaos:
dr-Chaos

Получается что Сноймановский sourceSocket из hackage.haskell.org без творения @qnikst hackage.haskell.org использовать толком нельзя.

@kb:
kb

Этот момент, когда ненависть переростает в дружбу.

ubuntuone.com

@segfault:
segfault

haskellforall.com
все наверно уже прочли, но вдруг.

@segfault:
segfault

А что если собирать трубу кондуитов с помощью стрелок? Это вообще возможно? Уж покуда кондуит имеет входной тип, выходной тип, и возвращаемый тип, то можно же иметь комбинаторы, превращающие кондуит в стрелку, где входной тип стрелки соответствует входному типу кондуита, а выходной тип стрелки соответственно выходноый тип кондуита, правда не понятно как быть с возвращаемым типом, возможно последняя стрелка должна просто свой результат биндить с возвратом кондуита, а не с его выходом.
Как идея? Подводные камни?

@segfault:
segfault

Есть где нибудь готовые инстансы MonadBaseControl IO для кондуитов ?

@segfault:
segfault

Смотр, жуик, у меня есть конструктор сурсов, например такой
createSourceA :: a -> Source m b
Я хочу создать другой сурс, который будет внутри создавать соурсы с помощью createSourceA и скармливать их на выход, естественно, до определенного условия выхода.
Как ?

@dr-Chaos:
dr-Chaos

Итак есть задача. Проксировать файл по HTTP с проверкой HMAC .
gist.github.com
Есть функция saveAndVerifyBody . Она берёт source и скармливает его 2-м zip-нутым синкам. Один из которых считает HMAC, а 2й записывает по временный файл.
Собственно, хочется сохранять не в файл а отправлять по HTTP дальше. Однако, как-то нормально это не придумывается, т.к. Request принимает как аргумент только Source :( Я пока пришёл только к схеме из функции saveAndVerifyBodyHttp .
Может вы чего подскажете?

@dr-Chaos:
dr-Chaos

кажись я въехал в эти ваши кондуиты применительно к http ...

@dr-Chaos:
dr-Chaos

Господа, есть вопрос по кондуитам.
Я хочу доработать биндинги для memcached-а. И одна из идей была использовать conduit-ы. И как я сейчас понимаю для этой задачи source/sink не особо то и нужны (т.е. обработка чанками в константной памяти конечно прикольно, однако в моём случае я всегда знаю размер), с другй стороны в yesod-е всё в resourceT и будет освобождение ресурсов в случае ексепшена.
Собственно вопрос, какие есть альтенативы и есть ли они вообще.

@qnikst:
qnikst

итак, мне хочется довольно странной вещи иметь буфферизуемый кондуит, который может проверять есть ли возможность пропихнуть данные в downstream и если нельзя, то продолжать брать данные из upstream. Для чего это мне нужно: хочется чтобы поток не простаивал на ожидании ресурса (возможности писать в сеть). Сложности: если данные из апстрима приходят редко, то можно попасть в ситуацию, когда поток висит ожидая этих данных, т.е. в этом случае хотелось бы иметь некий tryAwait/tryYield. Вопрос действительно ли это странно? возможно ли что это переусложнение на ровном месте? и как это можно реализовать?

Я вижу вариант с IORef: каждый поток атомарно его лочит, и использует ресурс, если ресурс залочен — возвращается к upstream. Этот вариант абсолютно не устойчив к недостатку данных из апстрима, плюс может привести к тому, что один из потоков не будет давать другому писать в ресурс. Первое обходится только гарантией того, что в апстриме будут данные, второе проверкой размера буффера, но это костыли.

Можно делать TMVar на апстрим и даунстрим, тогда не будет перечисленных выше проблем, но придется вводить поток, который будет отмечать готовность апстрима..

В общем мрак какой-то...

@qnikst:
qnikst

а это правильная реализация andThen? gist.github.com в смысле мне в "юзерском" потоке иногда надо вылавливать определенные события, в остальных случаях события должны уходить в /dev/null

@qnikst:
qnikst

binary-conduit кому-нить нужен, или так и оставлять одним модулем в проекте?

@alar:
alar

Кто вкурил, что такое кондуиты и зачем они нужны? Я сколько ни читаю Сноймана, не могу уловить принципиального отличия от ленивых списков.

@segfault:
segfault

почему не компилируется ? не понимаю, ведь Pipe это монад трансформер, он должен поднимать действие insert ?
bpaste.net

@segfault:
segfault

я правильно понял, что кондуиты — это возможность писать на хаскеле как на энергичном языке, фактически полностью в неком энергичном IO + освобождение ресурсов ?

@segfault:
segfault

похоже настало время задать этот вопрос. Iteratee ? Counduit ? Что лучше / хуже ? Зачем нужно уже понял.
Короче годных мануалов и всего такого реквестирую

@qrilka:
qrilka

посмотрел тут на html-conduit+dom-selector — Text и всё такое, но стрелки из hxt как-то всё-равно понятней для выборок сложней однострочников аля xpath

@qrilka:
qrilka

вроде тупая задача — получить файл по http и path из последнего запроса (ибо могут быть редиректы) — а считай за целый день так и не смог составить матрёшку из ResourceT и прочих IO

@qnikst:
qnikst

новое апи для кондуитов (yield, await,..) работает "всего-лишь" в 1.7 раз медленнее, чем старый вариант

@qnikst:
qnikst

принимаются идеи как реализовать функицю mergeSources :: (Monad m) => [Source m a] -> Source m a, которая по очереди тянет данные из источника и закрывает трубу если правая часть выполнена

@qnikst:
qnikst

есть такая штука: conduitState state1 =$= conduit2 , можно ли каким-нибудь чудом изменить state1 из conduit2 ?

@qnikst:
qnikst

не охота сразу в кафе писать так что может тут попробую.
есть поток данных из conduit [A|B], который нужно писать в несколько файлов, т.е. приходит событие A я начинаю создавать файл под него и писать
нужные события B в него; при этом одновременно запись может идти в несколько файлов. Вопрос в том, как это аккуратно реализовать, я вижу несколько вариантов:
1). сделать тупой sink который будет собирать все данные и выдавать результирующую структуру: минусы нифига не conduit-way, пользуется дофига оперативки,
программа будет выглядеть как лапша
2). воспользоваться stm-conduit и под каждый новый файл создавать канал, в который писать из sink-куда приходят данные и закрывать его, при необходимости,
плюсы: простое слежение за ресурсами, программа будет сильно понятнее, минусы неоправданное использование stm (есть реализация на IO-Channels, но она пока не
до конца рабочая)
3). можно-(ли?) создавать недовыполненный Pipe для записи в файл и в sink-е писать в соотвествующую трубу, тут интересный момент, что оно действие получается
недовыполненым: плюсы используется минимум лишних сущностей, минусы я не знаю как это правильно реализовать

@qnikst:
qnikst

что-то туплю, как с 0.4 кондуитами запустить liftIO $ src $$ snk, с 0.2 делалось liftIO $ runResourceT $ src $$ snk, а щас жутко на типы ругается

@qnikst:
qnikst

кондуиты немного поломали.. блин а вот с итератями такого не было (или не застал)