2010-03-25 5 views
9

Estoy leyendo una secuencia de datos grande usando cadenas de bytes perezosas, y quiero saber si al menos hay más bytes disponibles durante el análisis. Es decir, quiero saber si la longitud de la cadena de bytes es de al menos X bytes.En Haskell, ¿la longitud de llamada en un Lazy ByteString fuerza la cadena completa en la memoria?

¿Llamar a length dará como resultado que toda la secuencia se cargue, por lo tanto, se pierde el propósito de utilizar la cadena de bytes vago?

En caso afirmativo, el siguiente sería: ¿Cómo saber si tiene al menos X bytes sin cargar todo el flujo?

EDITAR: Originalmente pregunté en el contexto de la lectura de archivos pero entiendo que hay mejores formas de determinar el tamaño del archivo. La última solución que necesito, sin embargo, no debería depender de la fuente de bytesbyg lazy.

Respuesta

11

Sí.

length . take x.

+0

Gracias. Entonces la respuesta es sí, ¿usar length cargará toda la cadena en la memoria? – me2

+0

Sí, la longitud obligará a toda la lista y "cargarla". Por lo tanto, la contramedida en forma de "tomar" – ADEpt

+1

Entonces, para ser claros, todos entendemos, sí la longitud forzará la cadena en la memoria, por lo que si llama toma x primero, al menos solo está forzando los primeros x bytes en la memoria. – MtnViewMark

1

¿Hay alguna razón por la que no esté usando hFileSize :: Handle -> IO Integer para obtener la longitud del archivo?

+0

Sí, porque la entrada puede no ser realmente un archivo, sino una transmisión de red. No estoy interesado en la longitud real de los datos, sino en si hay datos suficientes para que los contenidos sean válidos (o truncados, en cuyo caso los datos están corruptos). – me2

+3

En cuyo caso no hay ningún programa en la Tierra que pueda encontrar la longitud de la secuencia sin leerla hasta el final. –

0

EDIT: lo siento. Creo que estaba pensando en que las cadenas de bytes eran listas. No hay una longitud genérica para las cadenas de bytes.

length es estricto porque el tipo que devuelve Int es estricto. Puede usar genericLength de Data.List e importar una biblioteca que define números perezosos de Peano y le da una instancia Num para ellos, por ejemplo, la biblioteca numbers:

Eso le permitiría expresar su función de la manera que desee, pero La respuesta de ephemient es funcionalmente la misma, y ​​no requiere importar una nueva biblioteca.

que acabo de hacer un post sobre el tema aquí, si eso suena como un enfoque que podría estar interesado en:

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

+0

ByteString no viene con su' genericLength' .Necesitas escribir uno tú mismo. – kennytm

+0

En algún lugar (probablemente en Hackage, aunque no puedo encontrarlo ahora) me encontré con un tipo de número natural "fragmentado", a lo largo de las líneas de 'datos Nat = Zero | Sum Integer Nat', que sería incluso más eficiente que la solución basada en 'take', probablemente. –

0

Se tendrá que recorrer toda la cadena, pero si no' Mantenga una referencia a toda la cadena de bytes flojos en cualquier otro lugar, creo que debería ser capaz de liberar la cabeza de la cuerda a medida que avanza hacia su cola.

Cuestiones relacionadas