Say I wanted to take the average of a list of floating point values, then at some point i need to use "sum" and "length" (built in functions). Can you make a function that calculates the average of arbitrary length list of Floating point values?
Asked
Active
Viewed 152 times
-2
-
1"Yes"? After all, you can just write your own `length` and `sum`. Note that the combination of `sum` and `length` usually leads to problems, though. – Zeta Mar 29 '16 at 12:27
-
Why would i get problems? – JJ chips Mar 29 '16 at 12:35
-
because `length` returns usually an `Int` and you will get trouble if you try to divide a `Float` (the sum) by said `Int` – Random Dev Mar 29 '16 at 12:42
-
1@Carsten: I'm thinking more in terms of `average [1..10^10]`. See RWH's chapter on profiling. – Zeta Mar 29 '16 at 12:50
-
1I'm voting to close this question as off-topic because it's an assignment, not a programming question. – dfeuer Mar 29 '16 at 18:20
2 Answers
1
You could use foldl'
to build up a tuple that includes both the running count of items as well as the running sum, then divide to get the average.
data StrictPair a b = StrictPair !a !b
myAvg :: Fractional a => [a] -> a
myAvg [] = error "Empty list"
myAvg list =
let
tupleSum (StrictPair count sum) x = StrictPair (count + 1) (sum + x)
StrictPair totalCount totalSum = foldl' tupleSum (StrictPair 0 0) list
in
totalSum / totalCount
The use of foldl'
and StrictPair
force evaluation to avoid memory issues. (thanks for the recommendation, @Jubobs, @Zeta, and @dfeuer!)

Chad Gilbert
- 36,115
- 4
- 89
- 97
-
2Too many thunks :p A left fold, with forced evaluation of the intermediate values, would make more sense, here, in my opinion. Richard Bird shows how to do exactly that in chapter 7 of his book *Thinking functionally with Haskell*. – jub0bs Mar 29 '16 at 12:45
-
@Jubobs is Bird's approach equivalent to `data Pair a b = Pair !a !b` together with `foldl'`? – Zeta Mar 29 '16 at 12:52
-
-
1The current code still isn't strict enough. You force the pairs, but not their components. – dfeuer Mar 29 '16 at 19:41
-
@ChadGilbert What dfeuer means is that `foldl'` doesn't force the evaluation of the elements of the pair (because the pair is already in [weak head normal form](http://stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal-form)). You need to either use a ["strict pair" type](https://hackage.haskell.org/package/strict-0.3.2/docs/Data-Strict-Tuple.html) for the accumulator, or use `seq` to force evaluation explicitly. – jub0bs Mar 30 '16 at 12:22
-
Thanks for the clarification on that, @Jubobs, it makes much more sense now. – Chad Gilbert Mar 30 '16 at 12:51
1
No, this is essentially impossible in general. Addition and division are necessary to calculate the mean of a list of numbers. The functions to calculate these for standard types like Rational
are "built in".

dfeuer
- 48,079
- 5
- 63
- 167