{- | Emping 0.6 (provisional) Tue 19 May 2009 05:51:44 PM CEST Module Codec transforms a list of lists of String attributes and values into a list of lists of Int tuples. The first argument of Strings (row) must contain the attribute names (may be blankId), the following argument lists (rows) must contain value names or blankId. The module also provides an Array function to display the names of AVp coded attributes and values -} module Codec (tableCode, tableToArray, AVp ) where import Control.Monad.State import Data.List (transpose, elemIndex) import Data.Array -- import CsvParse ( blankId ) (just a reminder) -- | AVp is the type synonym of an attribute-value tuple. type AVp = (Int, Int) -- check whether a value is in a list, append it, with its index, if not -- blankId is treated like any other value (or attribute) repl1 :: String -> State [String] Int repl1 x = State (\col -> case elemIndex x col of Nothing -> ((length col), col ++ [x]) Just i -> (i, col)) -- gets a list of unique values from a column of values getVals :: [String] -> [String] getVals strcol = execState (mapM repl1 strcol) [] -- constructs an index for each unique value in column of values getInds :: [String] -> [Int] getInds strcol = evalState (mapM repl1 strcol) [] -- get all unique values of each attribute from the original table avLs :: [[String]] -> [[String]] -- avLs [] = error "Codec avLs: table is empty" (checked in tableToArray) -- avLs (_:[]) = error "Codec avLs: table has 1 row" (see above) avLs tb = ((map getVals) . transpose . tail) tb {- | tableCode produces a list of lists of attribute-value tuples, coded as Int. A list of tuples represents a conjunction (and) of attribute values. The first Int of each AVp pair indexes into an array of Strings. The first element of each array element is the attribute name. The second Int of an AVp pair indexes into the second element of that array element, which is the list of value names of that attribute. See: tableToArray -} tableCode :: [[String]] -> [[AVp]] tableCode [] = error "Codec tableCode: table is empty" tableCode (_:[]) = error "Codec tableCode : table has 1 row" tableCode tb = map (zip [0..]) (values (tail tb)) where values = transpose . (map getInds) . transpose {- | tableToArray constructs an array of tuples of an attribute name and a list of its value names. The format for each element is (attribute name, list of value names). -} tableToArray :: [[String]] -> Array Int (String, [String]) tableToArray [] = error "Codec tableToArray: table is empty" tableToArray (_:[]) = error "Codec tableToArray: table has 1 row" tableToArray tb = listArray (0, (length (head tb)) -1) atplusvals where atplusvals = zip (head tb) (avLs tb)