Send Beginners mailing list submissions to
        beginners@haskell.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        beginners-requ...@haskell.org

You can reach the person managing the list at
        beginners-ow...@haskell.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Function to compute the mean (David James)


----------------------------------------------------------------------

Message: 1
Date: Mon, 10 May 2021 12:23:59 +0000
From: David James <dj112...@outlook.com>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <beginners@haskell.org>
Subject: Re: [Haskell-beginners] Function to compute the mean
Message-ID:
        
<am6pr04mb4214b5c6c0a798dfeb54eb62b6...@am6pr04mb4214.eurprd04.prod.outlook.com>
        
Content-Type: text/plain; charset="windows-1252"

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<http://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 
numbers<https://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 <beginners-boun...@haskell.org> on behalf of Joe King 
<joeking1...@yahoo.com>
Sent: Saturday, May 8, 2021 10:39:50 AM
To: beginners@haskell.org <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
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://mail.haskell.org/pipermail/beginners/attachments/20210510/7a5a0cdf/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: C41BD4BD0CBD4F519B49D2A93C03CE4A.png
Type: image/png
Size: 144 bytes
Desc: C41BD4BD0CBD4F519B49D2A93C03CE4A.png
URL: 
<http://mail.haskell.org/pipermail/beginners/attachments/20210510/7a5a0cdf/attachment-0001.png>

------------------------------

Subject: Digest Footer

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


------------------------------

End of Beginners Digest, Vol 154, Issue 5
*****************************************

Reply via email to