quitar principio numeros net intermedios inicio ignorar espacios entre eliminar como blanco haskell iteration bytestring iterate

principio - Haskell iteratee: ejemplo simple y simple de eliminar espacios en blanco.



quitar espacios en blanco excel 2016 (1)

Si solo quieres código, es esto:

procFile'' iFile oFile = fileDriver (joinI $ enumLinesBS ><> mapChunks (map rstrip) $ I.mapM_ (B.appendFile oFile)) iFile

Comentario:

Este es un proceso de tres etapas: primero transformas el flujo en bruto en un flujo de líneas, luego aplicas la función para convertir ese flujo de líneas y finalmente consumes el flujo. Como rstrip encuentra en la etapa intermedia, creará un transformador de flujo (Enumeratee).

Puede usar mapChunks o convStream , pero mapChunks es más simple. La diferencia es que mapChunks no le permite cruzar los límites de los fragmentos, mientras que convStream es más general. Prefiero convStream porque no expone ninguna de las implementaciones subyacentes, pero si mapChunks es suficiente, el código resultante suele ser más corto.

rstripE :: Monad m => Enumeratee [ByteString] [ByteString] m a rstripE = mapChunks (map rstrip)

Tenga en cuenta el map adicional en rstripE . El flujo externo (que es la entrada a rstrip) tiene el tipo [ByteString] , por lo que necesitamos mapear rstrip en él.

A modo de comparación, este es el aspecto que tendría si se implementara con convStream:

rstripE'' :: Enumeratee [ByteString] [ByteString] m a rstripE'' = convStream $ do mLine <- I.peek maybe (return B.empty) (/line -> I.drop 1 >> return (rstrip line)) mLine

Esto es más largo y menos eficiente porque solo aplicará la función rstrip a una línea a la vez, aunque haya más líneas disponibles. Es posible trabajar en toda la porción disponible actualmente, que está más cerca de la versión de mapChunks :

rstripE''2 :: Enumeratee [ByteString] [ByteString] m a rstripE''2 = convStream (liftM (map rstrip) getChunk)

De todos modos, con el enumLinesBS desmonte disponible, se compone fácilmente con el enumLinesBS enumeratee:

enumStripLines :: Monad m => Enumeratee ByteString [ByteString] m a enumStripLines = enumLinesBS ><> rstripE

El operador de composición ><> sigue el mismo orden que el operador de flecha >>> . enumLinesBS divide el flujo en líneas, luego rstripE . Ahora solo necesita agregar un consumidor (que es una iteración normal), y listo:

writer :: FilePath -> Iteratee [ByteString] IO () writer fp = I.mapM_ (B.appendFile fp) processFile iFile oFile = enumFile defaultBufSize iFile (joinI $ enumStripLines $ writer oFile) >>= run

Las funciones fileDriver son accesos directos para simplemente enumerar sobre un archivo y ejecutar la iteración resultante (desafortunadamente, el orden de los argumentos se cambia de enumFile):

procFile2 iFile oFile = fileDriver (joinI $ enumStripLines $ writer oFile) iFile

Addendum: aquí hay una situación en la que necesitaría el poder adicional de convStream. Supongamos que desea concatenar cada 2 líneas en una. No puedes usar mapChunks . Considere cuando el fragmento es un elemento singleton, [bytestring] . mapChunks no proporciona ninguna forma de acceder al siguiente fragmento, por lo que no hay nada más que concatenar con esto. Sin embargo, con convStream es simple:

concatPairs = convStream $ do line1 <- I.head line2 <- I.head return $ line1 `B.append` line2

esto se ve aún mejor en estilo aplicativo,

convStream $ B.append <$> I.head <*> I.head

Puede pensar que convStream consume continuamente una parte del flujo con la iteración provista, y luego envía la versión transformada al consumidor interno. A veces, incluso esto no es lo suficientemente general, ya que se llama la misma iteración en cada paso. En ese caso, puede usar unfoldConvStream para pasar el estado entre iteraciones sucesivas.

convStream y unfoldConvStream también permiten acciones monádicas, ya que la iteración de procesamiento de la secuencia es un transformador de mónada.

Estoy tratando de entender cómo usar la biblioteca iteratee con Haskell. Todos los artículos que he visto hasta ahora parecen centrarse en desarrollar una intuición sobre cómo se podrían construir las iteraciones, lo cual es útil, pero ahora que quiero bajar y usarlas, me siento un poco en el mar. Mirar el código fuente de iterate ha sido de valor limitado para mí.

Digamos que tengo esta función que recorta los espacios en blanco de una línea:

import Data.ByteString.Char8 rstrip :: ByteString -> ByteString rstrip = fst . spanEnd isSpace

Lo que me gustaría hacer es: convertir esto en una iteración, leer un archivo y escribirlo en otro lugar con el espacio en blanco al final de cada línea. ¿Cómo voy a estructurar eso con iteraciones? Veo que hay una función enumLinesBS en Data.Iteratee.Char en la que puedo ingresar, pero no sé si debería usar mapChunks o convStream o cómo volver a empaquetar la función anterior en una iteración.