
On Sat, Dec 10, 2011 at 07:21:58PM -0800, goodman.m.w@gmail.com wrote:
Hi beginners list,
I want to take a string of numbers and return the average. It is a string because I expect the input to be from STDIN or a file. I would like it to handle infinite lists. Further, I create the Stats data structure because later I will add support for other statistics, like max, min, sum, prod, etc. The following code works, but I'm not sure it's the proper way to do things in Haskell. For instance, maybe I could use a fold method instead of the explicit recursion in getStats?
You could indeed implement getStats with a fold, but we can even do one better.
-- avg.hs -- sm is sum, len is number of elements data Stats = Stats { sm :: Double, len :: Int } deriving Show
Let's add a Monoid instance for Stats, which specifies how two Stats objects should be combined: instance Monoid Stats where mempty = Stats 0 0 mappend (Stats sm1 len1) (Stats sm2 len2) = Stats (sm1 + sm2) (len1 + len2) We also specify how to create a default Stats object: mkStats x = Stats x 1 Now getStats is simply: getStats :: [Double] -> Stats getStats = mconcat . map mkStats That is, create a default Stats object from each list element, then combine/summarize them all using the Monoid instance. Other than that your code looks good to me. -Brent