I wrote code that parses a table header string in order to obtain two string tags, one for variable name (like GDP
) and another for unit of measurement (like bln_rub
). The tags collectively make a unique identifier for the table data.
Perhaps something can be done better/shorter/more easily readable?
import Data.List (isInfixOf)
type Label = Maybe String
data Variable = Variable
{ name :: Label,
unit :: Label
} deriving (Show, Eq)
makeVariable :: String -> String -> Variable
makeVariable name unit = Variable (Just name) (Just unit)
isDefined:: Variable -> Bool
isDefined var = (name var /= Nothing) && (unit var /= Nothing)
isIdentical:: Variable -> String -> String -> Bool
isIdentical var name unit = (makeVariable name unit) == var
-- Map allows a readable view of tuple-like
-- associative structure.
data Map = Map
{ label :: String,
texts :: [String] -- note: can use non-empty List
} deriving (Show)
nameMaps = [
Map "GDP" ["Gross domestic product"]
, Map "INDPRO" ["Industrial production"]
]
unitMaps = [
Map "bln_rub" ["bln rub", "billion ruble"]
, Map "rog" ["% change to previous period"] -- rate of growth
]
-- COMMENT: code below converts nameMaps and unitMaps
-- to list of tuples which are used for searching a header
asTuples :: Map -> [(String, String)]
asTuples (Map label texts) = [(text, label) | text <- texts]
findAllKeys :: [(String, String)] -> String -> [String]
findAllKeys mapper header = [key | tup@(text, key) <- mapper,
text `isInfixOf` header]
getLabel :: [Map] -> String -> Label
getLabel maps' header = case findAllKeys (flatten' maps') header of
[] -> Nothing
(x:_) -> Just x
where flatten' = concatMap asTuples
getName = getLabel nameMaps
getUnit = getLabel unitMaps
parseHeader text = Variable (getName text) (getUnit text)
x = parseHeader "Gross domestic product, bln rub"
flag = (isDefined x) && (isIdentical x "GDP" "bln_rub")
raise x = error ("Something wrong with: " ++ show x)
main = do
if flag then putStrLn $ show x else
raise x
return ()