[Haskell-beginners] Simple data summarization

Thomas Davie tom.davie at gmail.com
Tue Mar 10 11:49:15 EDT 2009


On 10 Mar 2009, at 16:26, Roland Zumkeller wrote:

> Hi Andy,
>
> Here is a function that parses a comma-separated list of strings:
>
>> uncommas :: String -> [String]
>> uncommas s = case break (==',') s of
>>              (w,[]) -> [w]
>>              (w,_:s') -> w : uncommas s'
>
> We can then sum over the 4th column like this:
>
>> main = putStrLn . show . sum . map (read . (!!4) . uncommas)
>>       . tail . lines =<< getContents
>
> This program is best read backwards: "getContents" gives stdin as a
> string and "lines" breaks it into lines. The (!!) function yields the
> nth element of a list. "read" and "show" convert between strings and
> integers.

An alternative solution, though similar is to implement a data type  
for each record, and implement read for it:

data Gender = Male | Female

data Ethnicity = European | Maori | ..........

data Record = R {name :: String, gender :: Gender, age :: Int,  
ethnicity :: Ethnicity, books :: Int}

instance Read Gender where
   readsPrec _ s = case toLower $ read s of {'m' -> [(Male,"")]; 'f' - 
 > [(Female,"")]; _ -> []}

instance Read Ethnicity where
   ...

instance Read Record where
   readsPrec _ = buildRec . uncommas
     where
       buildRec [n,g,a,e,b] =
         fromMaybe []
           do (n',_) <- listToMaybe $ reads n
              (g',_) <- listToMaybe $ reads g
              (a',_) <- listToMaybe $ reads a
              (e',_) <- listToMaybe $ reads e
              (b',_) <- listToMaybe $ reads b
              return [(R n' g' a' e' b', "")]

Now you can get at just the names for example by mapping the getter  
over the list:

main = putStrLn . ("Names: " ++) . concat . intersperse " " . map  
(name . read) . lines =<< getContents

Bob


More information about the Beginners mailing list