Array Processing Design Recipes

There are multiple ways to process arrays. In a language like Haskell, where recursion is the main control mechanism, there are two ways that you should be familar with.

Linear, item by item, processing.

Example linear scan. Printing each element of an array.

printEach :: Show a => Array a -> IO ()       -- write a contract
printEach a =                                 -- define the wrapper
  do { (low,high) <- boundsArr a              -- compute the bounds
     ; worker (low,high) a                    -- call the worker
     ; return ()                              -- clean up
     }

worker (low,high) a | low > high = return ()  -- base case
worker (low,high) a =                         -- step case has 2 actions
  do { item <- readArr a low                  -- 1) an action based upon low
     ; print item
     ; worker (low+1,high) a                  -- 2) make a recursive call
     }

Index pre-computation, and scan over index list.

An example of index precalculation

revIndexes :: (Int,Int) -> [(Int,Int)]
revIndexes (low,high) = zip countup countdown          -- Part 1, index precalculation
  where n = high - low + 1
        half = n `div` 2
        countup = [low..half]
        countdown = [high, high -1 .. low]

rev5 :: Array a -> IO ()
rev5 a =
  do { (low,high) <- boundsArr a
     ; let scan :: [(Int,Int)] -> IO ()               -- Part 2, defining scanning
           scan [] = return ()                        -- base case of scan
           scan ((i,j):xs) =                          -- step with 2 actions
              do { swap a (i,j); scan xs }
     ; scan (revIndexes (low,high))                   -- calling the scan step
     }
Back to the Daily Record.

Back to the class web-page.