Before we continue, here are all of the imports that we will be using in the remainder of this chapter:
-- file: ch12/Barcode.hs import Data.Array (Array(..), (!), bounds, elems, indices, ixmap, listArray) import Control.Applicative ((<$>)) import Control.Monad (forM_) import Data.Char (digitToInt) import Data.Ix (Ix(..)) import Data.List (foldl', group, sort, sortBy, tails) import Data.Maybe (catMaybes, listToMaybe) import Data.Ratio (Ratio) import Data.Word (Word8) import System.Environment (getArgs) import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.Map as M import Parse -- from chapter 11
The barcode encoding process can largely be table-driven, in which we use small tables of bit patterns to decide how to encode each digit. Haskell’s bread-and-butter—data types, lists, and tuples—are not well-suited to use for tables whose elements may be accessed randomly. A list has to be traversed linearly to reach the kth element. A tuple doesn’t have this problem, but Haskell’s type system makes it difficult to write a function that takes a tuple and an element offset and returns the element at that offset within the tuple. (We’ll explore why in the exercises that follow.)
The usual data type for constant-time random access is of course the array. Haskell provides several array data types. We’ll thus represent our encoding tables as arrays of strings.
The simplest array type is in the
Data.Array module, which we’re using here. This presents arrays that ...