Haskell: escanee una lista y aplique una función diferente para cada elemento

Necesito escanear un documento y acumular la salida de diferentes funciones para cada cadena en el archivo. La función que se ejecuta en cualquier línea del archivo depende de lo que esté en esa línea.

Podría hacer esto de manera muy ineficiente haciendo un pase completo a través del archivo para cada lista que quisiera recopilar. Pseudocódigo de ejemplo:

at :: B.ByteString -> Maybe Atom
at line
    | line == ATOM record = do stuff to return Just Atom
    | otherwise = Nothing

ot :: B.ByteString -> Maybe Sheet
ot line
    | line == SHEET record = do other stuff to return Just Sheet
    | otherwise = Nothing

Entonces, mapearía cada una de estas funciones sobre la lista completa de líneas en el archivo para obtener una lista completa de Átomos y Hojas:

mapper :: [B.ByteString] -> IO ()
mapper lines = do
    let atoms = mapMaybe at lines
    let sheets = mapMaybe to lines
    -- Do stuff with my atoms and sheets

Sin embargo, esto es ineficiente porque estoy mapeando toda la lista de cadenas para cada lista que estoy tratando de crear. En cambio, quiero mapear la lista de cadenas de línea solo una vez, identificar cada línea a medida que me muevo y luego aplicar la función adecuada y almacenar estos valores en diferentes listas.

Mi mentalidad C quiere hacer esto (pseudocódigo):

mapper' :: [B.ByteString] -> IO ()
mapper' lines = do
    let atoms = []
    let sheets = []
    for line in lines:
        | line == ATOM record = (atoms = atoms ++ at line)
        | line == SHEET record = (sheets = sheets ++ ot line)
    -- Now 'atoms' is a complete list of all the ATOM records
    --  and 'sheets' is a complete list of all the SHEET records

¿Cuál es la forma de hacer esto de Haskell? Simplemente no puedo lograr que mi mentalidad de programación funcional presente una solución.

Respuestas a la pregunta(8)

Su respuesta a la pregunta