Function to compute the mean

Greeetings I am new here and pretty new to Haskell. I was wondering what are the relative advanatges/disadvatnages of specifying a mean function in these two ways: mean :: [Double] -> Double mean xs = sum xs / fromIntegral (length xs) and mean1 :: (Real a, Fractional b) => [a] -> b mean1 xs = realToFrac (sum xs) / genericLength xs I understand that mean1 has the advantage that it can be called with lists of any Real type, so would work with things like foo :: [Int] foo = [1,2,3] mean foo -- type mismatch error mean1 foo -- no error But suppose that I know I will only ever use lists of Double, is there still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation. Are there any other considerations ? Thanks in advance JK

Hello,
In standard usage there is not much difference. But in Haskell, people
prefer to write in curried form (first implementation of yours) which has
the advantage of using partially applied form when suitable.
Regards.
Tarık Özkanlı
On Sat, 8 May 2021 at 12:43, Joe King
Greeetings I am new here and pretty new to Haskell.
I was wondering what are the relative advanatges/disadvatnages of specifying a mean function in these two ways:
mean :: [Double] -> Double mean xs = sum xs / fromIntegral (length xs)
and
mean1 :: (Real a, Fractional b) => [a] -> b mean1 xs = realToFrac (sum xs) / genericLength xs
I understand that mean1 has the advantage that it can be called with lists of any Real type, so would work with things like
foo :: [Int] foo = [1,2,3]
mean foo -- type mismatch error
mean1 foo -- no error
But suppose that I know I will only ever use lists of Double, is there still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation.
Are there any other considerations ?
Thanks in advance JK _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

No sorry,
Both are the same,
Discard my previous mail
Regards.
Tarık
On Sat, 8 May 2021 at 16:07, Tarik ÖZKANLI
Hello,
In standard usage there is not much difference. But in Haskell, people prefer to write in curried form (first implementation of yours) which has the advantage of using partially applied form when suitable.
Regards.
Tarık Özkanlı
On Sat, 8 May 2021 at 12:43, Joe King
wrote: Greeetings I am new here and pretty new to Haskell.
I was wondering what are the relative advanatges/disadvatnages of specifying a mean function in these two ways:
mean :: [Double] -> Double mean xs = sum xs / fromIntegral (length xs)
and
mean1 :: (Real a, Fractional b) => [a] -> b mean1 xs = realToFrac (sum xs) / genericLength xs
I understand that mean1 has the advantage that it can be called with lists of any Real type, so would work with things like
foo :: [Int] foo = [1,2,3]
mean foo -- type mismatch error
mean1 foo -- no error
But suppose that I know I will only ever use lists of Double, is there still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation.
Are there any other considerations ?
Thanks in advance JK _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Thank Tarik
Both are the same, Discard my previous mail
Bur surely they are not both the same, as I indicated in my initial email ?
Is it not the case that mean1 is a parametrically polymorphic functiion, while mean is a simple function ?
My question is about the relative advantages and disadvantes of each
Thanks again
J
On Saturday, May 8, 2021, 02:12:26 PM GMT+1, Tarik ÖZKANLI
Hello,
In standard usage there is not much difference. But in Haskell, people prefer to write in curried form (first implementation of yours) which has the advantage of using partially applied form when suitable.
Regards.
Tarık Özkanlı
On Sat, 8 May 2021 at 12:43, Joe King
wrote: Greeetings I am new here and pretty new to Haskell.
I was wondering what are the relative advanatges/disadvatnages of specifying a mean function in these two ways:
mean :: [Double] -> Double mean xs = sum xs / fromIntegral (length xs)
and
mean1 :: (Real a, Fractional b) => [a] -> b mean1 xs = realToFrac (sum xs) / genericLength xs
I understand that mean1 has the advantage that it can be called with lists of any Real type, so would work with things like
foo :: [Int] foo = [1,2,3]
mean foo -- type mismatch error
mean1 foo -- no error
But suppose that I know I will only ever use lists of Double, is there still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation.
Are there any other considerations ?
Thanks in advance JK _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hello Joe,
I meant they are the same in the curried - not curried sense. I
misinterpreted type constraints as actual inputs in tuple form.
Otherwise they are different of course :)
Although it depends on your specific requirements, the first one seems
better for me. It also does not give type error with [Int] inputs.
And It also has one less function call as you pointed hopefully more
efficient (if we don't miss other considerations)
Here is my little experiment with your mean function *but note that I let
ghc infer the type for me so it has different type than yours *:
*GHCi, version 9.0.1*
*ghci> let mean xs = sum xs / fromIntegral(length xs)ghci> mean
[2,3,5]3.3333333333333335ghci> :t meanmean :: (Fractional a, Foldable t) =>
t a -> a*
*ghci> *
Regards.
Tarık
On Sat, 8 May 2021 at 22:36, Joe King
Thank Tarik
Both are the same, Discard my previous mail
Bur surely they are not both the same, as I indicated in my initial email ?
Is it not the case that mean1 is a parametrically polymorphic functiion, while mean is a simple function ?
My question is about the relative advantages and disadvantes of each
Thanks again J
On Saturday, May 8, 2021, 02:12:26 PM GMT+1, Tarik ÖZKANLI < tozkanli2023@gmail.com> wrote:
No sorry,
Both are the same, Discard my previous mail
Regards.
Tarık
Hello,
In standard usage there is not much difference. But in Haskell, people
On Sat, 8 May 2021 at 16:07, Tarik ÖZKANLI
wrote: prefer to write in curried form (first implementation of yours) which has the advantage of using partially applied form when suitable. Regards.
Tarık Özkanlı
On Sat, 8 May 2021 at 12:43, Joe King
wrote: Greeetings I am new here and pretty new to Haskell.
I was wondering what are the relative advanatges/disadvatnages of
mean :: [Double] -> Double mean xs = sum xs / fromIntegral (length xs)
and
mean1 :: (Real a, Fractional b) => [a] -> b mean1 xs = realToFrac (sum xs) / genericLength xs
I understand that mean1 has the advantage that it can be called with
specifying a mean function in these two ways: lists of any Real type, so would work with things like
foo :: [Int] foo = [1,2,3]
mean foo -- type mismatch error
mean1 foo -- no error
But suppose that I know I will only ever use lists of Double, is there
still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation.
Are there any other considerations ?
Thanks in advance JK _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hello – I wanted to add some comments. mean is as you describe. mean1 as defined can take a list of any Real type, and return any Fractional type. These types need not be the same, and it’s up to the *caller* of mean1 to say what types they want to give and get returned, e.g. the following is possible:
:m +Data.Ratio :m +Data.Complex mean1 [6%5, 2%3] :: Complex Double 0.9333333333333333 :+ 0.0
This may not be what you were expecting, and maybe you want something like this:
mean2 :: (Fractional a) => [a] -> a
mean2 xs = sum xs / genericLength xs
(and note the realToFrac is then unces
From: Beginners

Ugh – sent too soon! Hello – I wanted to add some comments. mean is as you describe. mean1 as defined can take a list of any Real type, and return any Fractional type. These types need not be the same, and it’s up to the *caller* of mean1 to say what types they want to give and get returned, e.g. the following is possible:
:m +Data.Ratio :m +Data.Complex mean1 [6%5, 2%3] :: Complex Double 0.9333333333333333 :+ 0.0
This may not be what you were expecting? There’s also no need to restrict to Real, since it is valid to calculate the mean of a list of e.g. complex numbers. So maybe you want something like this:
mean2 :: (Fractional a) => [a] -> a
mean2 xs = sum xs / genericLength xs
(the realToFrac is now unnecessary). The caller still decides the type, but the argument and result type now have to be the same.
You can’t now do mean2 foo, but you can do mean2 [1,2,3] (and the 1, 2, 3 are interpreted as the default fractional type, probably Double).
I personally prefer to write “utility” functions to be as generic as possible. (Imagine you’re including them in some standard library for the whole world to use). But I’m sure there are other opinions.
Re performance, there is a comment against “genericLength” to say that it is not as efficient as length. And, as used above, this is the case. So maybe you actually want:
mean3 :: (Fractional a) => [a] -> a
mean3 xs = sum xs / fromIntegral (length xs)
which is as efficient as mean.
If you are especially interested in performance, you might want to read thishttp://book.realworldhaskell.org/read/profiling-and-optimization.html. It’s not really “beginner level” but does look at some issues with mean in some detail (and in particular why it can use so much memory and what you can do about that). Performance of Haskell code is often more difficult to predict than for other languages, for example due to lazy evaluation and some amazing transformations of you code done by GHC.
Incidentally, I am in the middle of drafting a page about numbershttps://en.wikibooks.org/wiki/User:Davjam2/Numbers to include in the Haskell wikibook that might be interesting. It discusses types, classes, defaults numeric conversions, etc. I would be very happy if for any feedback (please leave any on the “Discussion” tab on the page).
FYI: I tested performance (on GHC 8.4.3 on Windows) with this:
{-
compile: ghc -O2 -prof -fprof-auto -rtsopts Mean.hs
run: Mean +RTS -p > nul
-}
module Main (main) where
import Data.List
mean :: [Double] -> Double
mean xs = sum xs / fromIntegral (length xs)
mean1 :: (Real a, Fractional b) => [a] -> b
mean1 xs = realToFrac (sum xs) / genericLength xs
mean2 :: (Fractional a) => [a] -> a
mean2 xs = sum xs / genericLength xs
mean3 :: (Fractional a) => [a] -> a
mean3 xs = sum xs / fromIntegral (length xs)
mean4 :: (Fractional a) => [a] -> a
mean4 xs = sum xs / fromIntegral (genericLength xs :: Int)
main :: IO ()
main = do
let xs = [1 .. 10000000] :: [Double] --may default to Integer unless specified as Double.
print $ mean xs --change to mean1, etc, for different runs
And got:
Total time
Total alloc
mean
0.10
1,680,096,640 bytes
mean1
0.17
2,560,096,656 bytes
mean2
0.17
2,560,096,656 bytes
mean3
0.10
1,680,096,640 bytes
mean4
0.10
1,680,096,640 bytes
mean4 also uses genericLength but is as fast as length. This is due to some cleaverness in GHC, where it uses more efficient code when it knows the required result is integral.
From: Beginners

If you want a much more performant solution, go around the list once. Another advantage is that it will run in constant memory.
```
-- requires BangPatterns extension; bonus questions:
-- * Can you predict what will happen with out bang patterns?
-- * Would `foldl'` work even without any bang patterns?
mean5 :: [Double] -> Double
mean5 = snd . foldl (\(!n, !r) a -> (n + 1, a / n + (n - 1) / n * r)) (1, 0)
```
`mean5` on my system reports:
```
1,840,101,632 bytes allocated in the heap
197,896 bytes copied during GC
44,408 bytes maximum residency (2 sample(s))
29,320 bytes maximum slop
2 MiB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1774 colls, 0 par 0.005s 0.006s 0.0000s 0.0000s
Gen 1 2 colls, 0 par 0.000s 0.000s 0.0001s 0.0001s
INIT time 0.000s ( 0.000s elapsed)
MUT time 0.236s ( 0.235s elapsed)
GC time 0.005s ( 0.006s elapsed)
EXIT time 0.000s ( 0.000s elapsed)
Total time 0.241s ( 0.241s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 7,803,840,935 bytes per MUT second
Productivity 97.9% of total user, 97.5% of total elapsed
```
while `mean`
```
1,280,101,688 bytes allocated in the heap
1,099,489,280 bytes copied during GC
294,937,752 bytes maximum residency (12 sample(s))
50,518,888 bytes maximum slop
670 MiB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1209 colls, 0 par 0.379s 0.381s 0.0003s 0.0012s
Gen 1 12 colls, 0 par 0.976s 0.976s 0.0813s 0.3921s
INIT time 0.000s ( 0.000s elapsed)
MUT time 0.324s ( 0.322s elapsed)
GC time 1.355s ( 1.357s elapsed)
EXIT time 0.000s ( 0.000s elapsed)
Total time 1.679s ( 1.679s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 3,956,490,811 bytes per MUT second
Productivity 19.3% of total user, 19.2% of total elapsed
```
I compiled both with `ghc -O2 -rtsopts` and run them with `./Mean +RTS -s` (one does not nead to link the profiled RTS for `-s` to work).
Cheers,
Marcin
Sent with ProtonMail Secure Email.
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Monday, May 10th, 2021 at 14:23, David James
Ugh – sent too soon!
Hello – I wanted to add some comments. mean is as you describe.
mean1 as defined can take a list of any Real type, and return any Fractional type. These types need not be the same, and it’s up to the *caller* of mean1 to say what types they want to give and get returned, e.g. the following is possible:
:m +Data.Ratio
:m +Data.Complex
mean1 [6%5, 2%3] :: Complex Double
0.9333333333333333 :+ 0.0
This may not be what you were expecting? There’s also no need to restrict to Real, since it is valid to calculate the mean of a list of e.g. complex numbers. So maybe you want something like this:
mean2 :: (Fractional a) => [a] -> a
mean2 xs = sum xs / genericLength xs
(the realToFrac is now unnecessary). The caller still decides the type, but the argument and result type now have to be the same.
You can’t now do mean2 foo, but you can do mean2 [1,2,3] (and the 1, 2, 3 are interpreted as the default fractional type, probably Double).
I personally prefer to write “utility” functions to be as generic as possible. (Imagine you’re including them in some standard library for the whole world to use). But I’m sure there are other opinions.
Re performance, there is a comment against “genericLength” to say that it is not as efficient as length. And, as used above, this is the case. So maybe you actually want:
mean3 :: (Fractional a) => [a] -> a
mean3 xs = sum xs / fromIntegral (length xs)
which is as efficient as mean.
If you are especially interested in performance, you might want to read this. It’s not really “beginner level” but does look at some issues with mean in some detail (and in particular why it can use so much memory and what you can do about that). Performance of Haskell code is often more difficult to predict than for other languages, for example due to lazy evaluation and some amazing transformations of you code done by GHC.
Incidentally, I am in the middle of drafting a page about numbers to include in the Haskell wikibook that might be interesting. It discusses types, classes, defaults numeric conversions, etc. I would be very happy if for any feedback (please leave any on the “Discussion” tab on the page).
FYI: I tested performance (on GHC 8.4.3 on Windows) with this:
{-
compile: ghc -O2 -prof -fprof-auto -rtsopts Mean.hs
run: Mean +RTS -p > nul
-}
module Main (main) where
import Data.List
mean :: [Double] -> Double
mean xs = sum xs / fromIntegral (length xs)
mean1 :: (Real a, Fractional b) => [a] -> b
mean1 xs = realToFrac (sum xs) / genericLength xs
mean2 :: (Fractional a) => [a] -> a
mean2 xs = sum xs / genericLength xs
mean3 :: (Fractional a) => [a] -> a
mean3 xs = sum xs / fromIntegral (length xs)
mean4 :: (Fractional a) => [a] -> a
mean4 xs = sum xs / fromIntegral (genericLength xs :: Int)
main :: IO ()
main = do
let xs = [1 .. 10000000] :: [Double] --may default to Integer unless specified as Double.
print $ mean xs --change to mean1, etc, for different runs
And got:
Total time
Total alloc
mean
0.10
1,680,096,640 bytes
mean1
0.17
2,560,096,656 bytes
mean2
0.17
2,560,096,656 bytes
mean3
0.10
1,680,096,640 bytes
mean4
0.10
1,680,096,640 bytes
mean4 also uses genericLength but is as fast as length. This is due to some cleaverness in GHC, where it uses more efficient code when it knows the required result is integral.
[C41BD4BD0CBD4F519B49D2A93C03CE4A.png]
From: Beginners
on behalf of Joe King
Sent: Saturday, May 8, 2021 10:39:50 AM
To: beginners@haskell.org
Subject: [Haskell-beginners] Function to compute the mean
Greeetings I am new here and pretty new to Haskell.
I was wondering what are the relative advanatges/disadvatnages of specifying a mean function in these two ways:
mean :: [Double] -> Double
mean xs = sum xs / fromIntegral (length xs)
and
mean1 :: (Real a, Fractional b) => [a] -> b
mean1 xs = realToFrac (sum xs) / genericLength xs
I understand that mean1 has the advantage that it can be called with lists of any Real type, so would work with things like
foo :: [Int]
foo = [1,2,3]
mean foo
-- type mismatch error
mean1 foo
-- no error
But suppose that I know I will only ever use lists of Double, is there still any advantage (or disadvantage of using mean1). For example is there any performance benefit by using mean in that case since mean1 has additional function evaluation.
Are there any other considerations ?
Thanks in advance
JK
_______________________________________________
Beginners mailing list
Beginners@haskell.org
participants (4)
-
coot@coot.me
-
David James
-
Joe King
-
Tarik ÖZKANLI