[Haskell-beginners] Averaging a string of numbers
Brent Yorgey
byorgey at seas.upenn.edu
Sun Dec 11 16:19:05 CET 2011
On Sat, Dec 10, 2011 at 07:21:58PM -0800, goodman.m.w at 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
More information about the Beginners
mailing list