title: Haskell: Scan Through a List and Apply A Different Function for Each Element
body: <p>I need to scan through a document and accumulate the output of different functions for each string in the file.  The function run on any given line of the file depends on what is in that line.  </p>
  
  <p>I could do this very inefficiently by making a complete pass through the file for every list I wanted to collect.  Example pseudo-code:</p>
  
  <pre><code>at :: B.ByteString -&gt; Maybe Atom
  at line
      | line == ATOM record = do stuff to return Just Atom
      | otherwise = Nothing
  
  ot :: B.ByteString -&gt; Maybe Sheet
  ot line
      | line == SHEET record = do other stuff to return Just Sheet
      | otherwise = Nothing
  </code></pre>
  
  <p>Then, I would map each of these functions over the entire list of lines in the file to get a complete list of Atoms and Sheets:</p>
  
  <pre><code>mapper :: [B.ByteString] -&gt; IO ()
  mapper lines = do
      let atoms = mapMaybe at lines
      let sheets = mapMaybe to lines
      -- Do stuff with my atoms and sheets
  </code></pre>
  
  <p>However, this is inefficient because I am maping through the entire list of strings for every list I am trying to create.  Instead, I want to map through the list of line strings only once, identify each line as I am moving through it, and then apply the appropriate function and store these values in different lists.</p>
  
  <p>My C mentality wants to do this (pseudo code):</p>
  
  <pre><code>mapper' :: [B.ByteString] -&gt; 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
  </code></pre>
  
  <p>What is the Haskell way of doing this?  I simply can't get my functional-programming mindset to come up with a solution.  </p>