Будет ли в Haskell вызов length для Lazy ByteString заставлять всю строку помещаться в память?

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

Приведет ли вызов length к загрузке всего потока, что приведет к отмене цели использования ленивой строки байтов?

Если да, то продолжение будет таким: как узнать, есть ли у него хотя бы X байтов, не загружая весь поток?

РЕДАКТИРОВАТЬ: Первоначально я спрашивал в контексте чтения файлов, но понимаю, что есть лучшие способы определить размер файла. Однако окончательное решение, которое мне нужно, не должно зависеть от ленивого источника строки байтов.


person me2    schedule 25.03.2010    source источник


Ответы (4)


да.

length . take x.

person ephemient    schedule 25.03.2010
comment
Спасибо. Итак, ответ — да, использование длины загрузит всю строку в память? - person me2; 25.03.2010
comment
Да, длина заставит весь список и загрузить: это. Таким образом, контрмера в виде взятия - person ADEpt; 25.03.2010
comment
Итак, чтобы быть ясным, мы все понимаем, что yes length заставит строку помещаться в память, поэтому, если вы сначала вызовете take x, то, по крайней мере, вы принудительно поместите в память только первые x байтов. - person MtnViewMark; 25.03.2010
comment
@MtnViewMark: это, вероятно, потребует более x байтов, поскольку строгость ленивых строк байтов применяется для каждого фрагмента. Форсирование первого символа чанка также форсирует остальную часть этого чанка. - person porges; 25.03.2010
comment
Извините за короткий ответ, я написал его быстро и не успел вернуться и расширить его. Да, length форсирует всю строку, а length . take x форсирует только фрагменты, содержащие первые x байта, которые могут быть больше x байтов. Я думаю, что размер куска по умолчанию где-то около 31 КБ. - person ephemient; 25.03.2010

Есть ли причина, по которой вы не используете hFileSize :: Handle -> IO Integer для получения длины файла?

person yatima2975    schedule 25.03.2010
comment
Да потому что на входе может быть не файл, а сетевой поток. Меня интересует не фактическая длина данных, а то, достаточно ли данных, чтобы сделать содержимое действительным (или усеченным, и в этом случае данные повреждены). - person me2; 25.03.2010
comment
В таком случае на Земле нет программы, которая могла бы найти длину потока, не читая его до конца. - person Paul Johnson; 28.03.2010

РЕДАКТИРОВАТЬ: извините. Наверное, я думал, что строки байтов - это списки. Для строк байтов нет genericLength.

length является строгим, потому что тип, который он возвращает, Int является строгим. Вы можете использовать genericLength из Data.List и импортировать библиотеку, которая определяет ленивые числа Пеано и предоставляет вам экземпляр Num для них, например, numbers:

Это позволило бы вам выразить свою функцию так, как вам хотелось бы, но ответ ephemient функционально такой же и не требует импорта новой библиотеки.

Я только что сделал сообщение в блоге по этому вопросу здесь, если это похоже на подход, который может вас заинтересовать:

http://coder.bsimmons.name/blog/2010/03/lazy-arithmetic-in-haskell/

person jberryman    schedule 25.03.2010
comment
ByteString не поставляется со своим genericLength. Вам нужно написать один самостоятельно. - person kennytm; 25.03.2010
comment
Где-то (вероятно, на Hackage, хотя я не могу найти его сейчас) я наткнулся на блокированный натуральный числовой тип, похожий на data Nat = Zero | Sum Integer Nat, который, вероятно, был бы даже более эффективным, чем решение на основе take. - person Reid Barton; 25.03.2010

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

person Peaker    schedule 29.03.2010