Odd values when enumerating a list - haskell

As part of a larger function definition, I needed to allow the domain (i, n) of a function to increment from i to n at varying rates. So I wrote:
f (i, n) k = [i, (i+k)..n]
into GHC. This returned odd results:
*Main> f (0.0, 1.0) 0.1
[0.0,0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]
Why does GHC return, e.g., 0.30000000000000004 instead of 0.3?

Because IEEE floating point arithmetic can't express decimal numbers precisely, in general. There is always a rounding error in the binary representation, which sometimes seeps to the surface when displaying the number.
Depending on how GHC converts floating-point numbers to a decimal representation, you might find that on Windows it displays the result as the expected 0.3. This is because Microsoft's runtime libraries are smarter than Linux and Mac about how they present floats.
EDIT: This may not be the case. The number 0.3 will encode as the integer 3fd3333333333333 when using IEEE floats, whereas 0.1 + 0.1 + 0.1 will produce a number that encodes as 3fd3333333333334, and I don't know whether Microsoft's runtime libraries are tolerant enough to round back to 0.3 when displaying this.
In any event, a good example of the different handling is to type 0.3 into a Python interactive shell. If it's Python 2.6, you'll get back 0.29999999999999999, and if it's 2.7, it will display 0.3.

If i, n, and k are rational, you could go the infinite-precision route:
f :: (Rational, Rational) -> Rational -> [Rational]
f (i, n) k = [i, (i+k) .. n]
The notation may require a bit of getting used to:
ghci> f (0%1, 1%1) (1%10)
[0 % 1,1 % 10,1 % 5,3 % 10,2 % 5,1 % 2,3 % 5,7 % 10,4 % 5,9 % 10,1 % 1]
Think of the % as a funny looking fraction bar.
You could view approximations with
import Control.Monad (mapM_)
import Data.Ratio (Rational, (%), denominator, numerator)
import Text.Printf (printf)
printApprox :: [Rational] -> IO ()
printApprox rs = do
mapM_ putRationalToOnePlaceLn rs
where putRationalToOnePlaceLn :: Rational -> IO ()
putRationalToOnePlaceLn r = do
let toOnePlace :: String
toOnePlace = printf "%.1f" (numFrac / denomFrac)
numFrac, denomFrac :: Double
numFrac = fromIntegral $ numerator r
denomFrac = fromIntegral $ denominator r
putStrLn toOnePlace
The code above is written in an imperative style with full type annotations. Read its type as transforming a list of rational numbers into some I/O action. The mapM_ combinator from Control.Monad evaluates an action (putRationalToOnePlaceLn in this case) for each value in a list (the rationals we want to approximate). You can think of it as sort of a for loop, and there is even a forM_ combinator that's identical to mapM_ except the order of the arguments is reversed. The underscore at the end is a Haskell convention showing that it discards the results of running the actions, and note that there are mapM and forM that do collect those results.
To arrange for the output of the approximations via putStrLn, we have to generate a string. If you were writing this in C, you'd have code along the lines of
int numerator = 1, denominator = 10;
printf("%.1f\n", (double) numerator / (double) denominator);
The Haskell code above is similar in structure. The type of Haskell's / operator is
(/) :: (Fractional a) => a -> a -> a
This says for some instance a of the typeclass Fractional, when given two values of the same type a, you'll get back another value of that type.
We can ask ghci to tell us about Fractional:
ghci> :info Fractional
class (Num a) => Fractional a where
(/) :: a -> a -> a
recip :: a -> a
fromRational :: Rational -> a
-- Defined in GHC.Real
instance Fractional Float -- Defined in GHC.Float
instance Fractional Double -- Defined in GHC.Float
Notice the instance lines at the bottom. This means we can
ghci> (22::Float) / (7::Float)
3.142857
or
ghci> (22::Double) / (7::Double)
3.142857142857143
but not
ghci> (22::Double) / (7::Float)
<interactive>:1:16:
Couldn't match expected type `Double' against inferred type `Float'
In the second argument of `(/)', namely `(7 :: Float)'
In the expression: (22 :: Double) / (7 :: Float)
In the definition of `it': it = (22 :: Double) / (7 :: Float)
and certainly not
ghci> (22::Integer) / (7::Integer)
<interactive>:1:0:
No instance for (Fractional Integer)
arising from a use of `/' at :1:0-27
Possible fix: add an instance declaration for (Fractional Integer)
In the expression: (22 :: Integer) / (7 :: Integer)
In the definition of `it': it = (22 :: Integer) / (7 :: Integer)
Remember that Haskell's Rational type is defined as a ratio of Integers, so you can think of fromIntegral as sort of like a typecast in C.
Even after reading A Gentle Introduction to Haskell: Numbers, you'll still likely find Haskell to be frustratingly picky about mixing numeric types. It's too easy for us, who perform infinite-precision arithmetic in our heads or on paper, to forget that computers have only finite precision and must deal in approximations. Type safety is a helpful reality check.
Sample output:
*Main> printApprox $ f (0%1, 1%1) (1%10)
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
The definition of printApprox probably seemed comforting with all the helpful signposts such as names of functions and parameters or type annotations. As you grow more experienced and comfortable with Haskell, such imperative-looking definitions will begin to look cluttered and messy.
Haskell is a functional language: its strength is specifying the what, not the how, by assembling simple functions into more complex ones. Someone once suggested that Haskell manipulates functions as powerfully as Perl manipulates strings.
In point-free style, the arguments disappear leaving the structure of the computation. Learning to read and this style does take practice, but you'll find that it helps write cleaner code.
With tweaks to the imports, we can define a point-free equivalent such as
import Control.Arrow ((***), (&&&))
import Control.Monad (join, mapM_)
import Data.Ratio (Rational, (%), denominator, numerator)
import Text.Printf (printf)
printApproxPointFree :: [Rational] -> IO ()
printApproxPointFree =
mapM_ $
putStrLn .
toOnePlace .
uncurry (/) .
join (***) fromIntegral .
(numerator &&& denominator)
where toOnePlace = printf "%.1f" :: Double -> String
We see a few familiar bits: our new friend mapM_, putStrLn, printf, numerator, and denominator.
There's also some weird stuff. Haskell's $ operator is another way to write function application. Its definition is
f $ x = f x
It may not seem terribly useful until you try
Prelude> show 1.0 / 2.0
<interactive>:1:0:
No instance for (Fractional String)
arising from a use of `/' at :1:0-13
Possible fix: add an instance declaration for (Fractional String)
In the expression: show 1.0 / 2.0
In the definition of `it': it = show 1.0 / 2.0
You could write that line as
show (1.0 / 2.0)
or
show $ 1.0 / 2.0
So you can think of $ as another way to write parentheses.
Then there's . that means function composition. Its definition is
(f . g) x = f (g x)
which we could also write as
(f . g) x = f $ g x
As you can see, we apply the right-hand function and then feed the result to the left-hand function. You may remember definitions from mathematics textbooks such as
The name . was chosen for its similarity in appearance to the raised dot.
So with a chain of function compositions, it's often easiest to understand it by reading back-to-front.
The (numerator &&& denominator) bit uses a fan-out combinator from Control.Arrow. For example:
ghci> (numerator &&& denominator) $ 1%3
(1,3)
So it applies two functions to the same value and gives you back a tuple with the results. Remember we need to apply fromIntegral to both the numerator and denominator, and that's what join (***) fromIntegral does. Note that *** also comes from the Control.Arrow module.
Finally, the / operator takes separate arguments, not a tuple. Thinking imperatively, you might want to write something like
(fst tuple) / (snd tuple)
where
fst (a,_) = a
snd (_,b) = b
but think functionally! What if we could somehow transform / into a function that takes a tuple and uses its components as arguments for the division? That's exactly what uncurry (/) does!
You've taken a great first step with Haskell. Enjoy the journey!

A better way of doing this is more along the lines of
map (/10) [0 .. 10]
This takes whole numbers, thereby avoiding the float problem, and divides each one by 10.

Related

Execution order of list comprehension filtering

Just started learning Haskell and came across this issue.
If I have a list comprehension with a condition such as
[x*2 | x<- [1..10], x `mod` 3 ==2]
I get
[4,10,16]
as expected. However, if I have instead
[x**2 | x<- [1..10], x `mod` 3 ==2]
It is has the type variable as ambiguous for the mod function. I presume this is because x2 promotes an integer to a float, but why does this affect the conditional? Why is the type ambiguous in this case? Does it calculate x2, and then square root it? (This seems highly improbable) Does it somehow keep track of the x that generated each x2 term?
Perhaps it's the imperative mindset, but internally, I thought the execution would be along the lines of [in python]
lst=[]
for x in range(10):
if x%3==2:
lst.append(x**2)
Could someone clarify/correct my understanding?
Let's have a look at the types of mod and (**):
mod :: Integral n => n -> n -> n
(**) :: Floating a => a -> a -> a
-- hm......
mod and (**) put other constraints on the used type. mod expects an integral type (Int, Integer), whereas (**) expects a floating type (Float, Double). Since there's no type that's both integral and a floating point number, GHC gives up.
Instead, use (^):
(^) :: (Integral n, Num a) => a -> n -> a
E.g.
[x ^ 2 | x <- [1..10], x `mod` 3 == 2]
By the way, you can find errors like this easier if you try to give a type to the result:
ghci> [x ** 2 | x <- [1..10], x `mod` 3 == 2] :: [Int]
<interactive>:1:4:
No instance for (Floating Int) arising from a use of `**'
In the expression: x ** 2
...
The first example works because of defaulting. The expression is inferred as having type
Integral a => [a]
and then the a type variable is defaulted to Integer for convenience.
In the second expression, the use of ** forces x to be Floating and the mod forces it to be Integral. So GHC infers that the expression has type
(Integral a, Floating a) => [a]
There is no standard numeric type that is both Integral and Floating, let alone one that participates in defaulting.
You mentioned the notion of numeric promotion in your question. C, C++, Java, and maybe some other languages have such a thing. Haskell does not, and those of us who use it tend to be grateful for that. All conversions from one numeric type to another have to be done using explicit conversion functions like fromIntegral, fromRational, round, floor, %, etc.
You probably meant to use ^ instead of **, which would leave just the Integral a constraint. In a real program, you should generally avoid the defaulting mechanism by including a type signature. You can turn it off altogether using
default ()
somewhere in your module.
List comprehension in haskell desugars to a do-block using the list monad. In your example, it would be something like:
x <- [1..10]
guard $ (x `mod` 3) == 2
return $ x**2
In this case it attempts to unify the types of (**) x 2 and mod x 3 which fails because you can't unify a Floating type with an Integral type without explicitly converting between the two.
You've got a few options: use (^^) instead of (**) or do ((fromIntegral x) ** 2) if you want x to be an integral type, or somehow round x to an integral type if you want it to be a floating type.

Function to Calculate `log` of Integer

I wrote the following function.
f :: Integer -> Integer
f x = if (odd x) then 0 else (floor . logBase 2) x
But the following compile-time error occurs:
F.hs:2:31:
No instance for (RealFrac Integer) arising from a use of floor'
Possible fix: add an instance declaration for (RealFrac Integer)
In the first argument of(.)', namely `floor'
In the expression: floor . logBase 2
In the expression: (floor . logBase 2) x
F.hs:2:39:
No instance for (Floating Integer) arising from a use of logBase'
Possible fix: add an instance declaration for (Floating Integer)
In the second argument of(.)', namely `logBase 2'
In the expression: floor . logBase 2
In the expression: (floor . logBase 2) x Failed, modules loaded: none.
How can I properly write the above function?
This will be a tad long, as I would like to not just give you code that works, but explain the issue in depth so you can understand GHC's type errors better.
As already answered briefly (and as the type error tries its best to tell you, although it is certainly not clear enough), in order to use logBase x y, the two parameters x and y must both be instances of the "floating point" typeclasses.
In particular, logBase is a method of the Floating typeclass (from the Prelude's documentation):
class Fractional a => Floating a where Source
logBase :: a -> a -> a
We also find, also from the Prelude:
class (Real a, Fractional a) => RealFrac a where Source
floor :: Integral b => a -> b
That is, in order to use the function (floor . logBase), we need two parameters which are Fractional (since logBase requires this), and Real (since floor requires both). The merger of these two is defined as RealFrac, and that's exactly what GHC is complaining you failed to provide it (in your function's type declaration).
Why is it complaining? From the Prelude we find the following instance declarations for RealFrac. Note that "RealFrac Integer" is missing:
RealFrac Double
RealFrac Float
RealFrac CDouble
RealFrac CFloat
Integral a => RealFrac (Ratio a)
HasResolution a => RealFrac (Fixed a)
The way Haskell works, is that if you give it an integer literal (consecutive digits without a decimal point), it will assume that it belongs to the Integral typeclass (and will try to figure out whether to make it an Integer or Int implicitly), but it will never implicitly promote an integer literal to one of the Fractional classes (including RealFrac). Since there is no "RealFrac Integer" line, this means that you can't expect Haskell to compile your code.
You are telling Haskell that you will give it Integral instances by your explicit type declaration (this is one of the reasons why these are generally a good idea -- Haskell would have quietly accepted your function declaration otherwise, only to throw compilation errors in the client functions that use it):
f :: Integer -> Integer
The solution is to promote your integers by using the following function (which converts Integrals into any compatible Number types):
fromIntegral :: (Integral a, Num b) => a -> b
Floor performs the conversion in the opposite direction (from Fractional to Integral), as shown by its type.
In conclusion you need to simply say
f :: Integer -> Integer
f x = if (odd x) then 0 else (floor . logBase 2.0 . fromIntegral) x
Note the fromIntegral call to make the type of the parameter compatible with what the compiler expects, as well as the use of 2.0 (a Fractional literal) for the base.
Beware that logBase requires conversion to a Floating type, which may lead to erroneous results.
f :: Integer -> Integer
f x = if (odd x) then 0 else (floor . logBase 2.0 . fromIntegral) x
λ> f (2^99999)
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
This happens because (2^99999 :: Double) = Infinity, and the floor Infinity apparently evaluates to... something surprising.
The integer-logarithms package provides an integerLog2 function which works better:
λ> import Math.NumberTheory.Logarithms
λ> integerLog2 (2^99999)
99999
it :: Int
The function in integer-logarithms is just a thin wrapper around integer-gmp, so you could also use that directly:
λ> :set -XMagicHash
λ> import GHC.Exts
λ> import GHC.Integer.Logarithms
λ> I# (integerLog2# (2^99999))
99999
it :: Int
Note that these functions return a value even if the result is not a power of two:
λ> integerLog2 1023
9

converting list of type Integer to list of type Int

i'm trying to convert this list [1..20] from [Integer] to [Int]
map fromInteger [1..20]
however this still gives me a list of Integers
This on its own converts 2 which is Integer type to Int
fromInteger 2 :: Int
What's wrong
In Haskell, values can – just like functions – be polymorphic.
This idea is familiar to most programmers for the numerical operators: nobody finds it strange that 5 + 6 works, yielding and integer, just as fine as 3.14159 + 2.71828 works yielding a float. But in languages like C this is done pretty much ad-hoc, just because this special case is so handy. This brings a lot of problems with it, in particular when you write things like 1/12, which will carry out the / as integer-division, resulting in 0. Clearly not the intended thing when ou use it in something like
for (double hourWay = 0; hourWay<1; hourWay += 1/12)
double theta = hourWay * 2 * pi;
...
So programmers have to resort to ugly hacks like writing out the fraction in decimal, or explicitly making one of the numbers float (1.0 / 12.0, urgh!).
Haskell does this automatically for us: when it sees the result will be a double (that's explicitly written out in hourWays declaration) it makes no sense to start that calculation with integers, so it interprets 1 and 12 as floating-point right away. No problem with that since the integers certainly form a subset of the reals1. You can directly access this functionality by giving explicit type signatures:
Prelude> 4 :: Int
4
Prelude> 4 :: Double
4.0
Note that :: Double does not convert the number. 4 by itself does not have any particular type at all, it's polymorphic: whatever number type you want, 4 is a valid description; this is expressed in the type system by the signature
Prelude> :t 4
4 :: Num a => a
And in particular, this means
Prelude> :t [1..20]
[1..20] :: (Num t, Enum t) => [t]
is also polymorphic, which allows you to write
Prelude> [1..20] :: [Int]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
Prelude> [1..20] :: [Double]
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0]
Only when you don't give any signature, ghci will default to the "safest bet", which is Integer.
So in the case of [1..20] you don't need fromInteger at all. You would need it though if some elements weren't given directly as literals, but external constants / arguments of fixed type Integer.
Prelude> let x = 13 :: Integer
Prelude> :t [1..12]++[x]++[14..20]
[1..12]++[x]++[14..20] :: [Integer]
Prelude> map fromInteger ([1..12]++[x]++[14..20]) :: [Int]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
This works again with any numerical result type you request, because although x prevents [1..12]++[x]++[14..20] from being polymorphic, fromInteger re-introduces that.
Prelude> :t map fromInteger ([1..12]++[x]++[14..20]) :: [Int]
map fromInteger ([1..12]++[x]++[14..20]) :: Num b => [b]
1Which doesn't actually mean Double forms a subtype of Integer or even Int... it doesn't; but this becomes a problem only for big numbers.

I don't understand number conversions in Haskell

Here is what I'm trying to do:
isPrime :: Int -> Bool
isPrime x = all (\y -> x `mod` y /= 0) [3, 5..floor(sqrt x)]
(I know I'm not checking for division by two--please ignore that.)
Here's what I get:
No instance for (Floating Int)
arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt x)'
In the expression: floor (sqrt x)
In the second argument of `all', namely `[3, 5 .. floor (sqrt x)]'
I've spent literally hours trying everything I can think of to make this list using some variant of sqrt, including nonsense like
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
It seems that (sqrt 500) works fine but (sqrt x) insists on x being a Floating (why?), and there is no function I can find to convert an Int to a real (why?).
I don't want a method to test primality, I want to understand how to fix this. Why is this so hard?
Unlike most other languages, Haskell distinguishes strictly between integral and floating-point types, and will not convert one to the other implicitly. See here for how to do the conversion explicitly. There's even a sqrt example :-)
The underlying reason for this is that the combination of implicit conversions and Haskel's (rather complex but very cool) class system would make type reconstruction very difficult -- probably it would stretch it beyond the point where it can be done by machines at all. The language designers felt that getting type classes for arithmetic was worth the cost of having to specify conversions explicitly.
Your issue is that, although you've tried to fix it in a variety of ways, you haven't tried to do something x, which is exactly where your problem lies. Let's look at the type of sqrt:
Prelude> :t sqrt
sqrt :: (Floating a) => a -> a
On the other hand, x is an Int, and if we ask GHCi for information about Floating, it tells us:
Prelude> :info Floating
class (Fractional a) => Floating a where
pi :: a
<...snip...>
acosh :: a -> a
-- Defined in GHC.Float
instance Floating Float -- Defined in GHC.Float
instance Floating Double -- Defined in GHC.Float
So the only types which are Floating are Floats and Doubles. We need a way to convert an Int to a Double, much as floor :: (RealFrac a, Integral b) => a -> b goes the other direction. Whenever you have a type question like this, you can ask Hoogle, a Haskell search engine which searches types. Unfortunately, if you search for Int -> Double, you get lousy results. But what if we relax what we're looking for? If we search for Integer -> Double, we find that there's a function fromInteger :: Num a => Integer -> a, which is almost exactly what you want. And if we relax our type all the way to (Integral a, Num b) => a -> b, you find that there is a function fromIntegral :: (Integral a, Num b) => a -> b.
Thus, to compute the square root of an integer, use floor . sqrt $ fromIntegral x, or use
isqrt :: Integral i => i -> i
isqrt = floor . sqrt . fromIntegral
You were thinking about the problem in the right direction for the output of sqrt; it returned a floating-point number, but you wanted an integer. In Haskell, however, there's no notion of subtyping or implicit casts, so you need to alter the input to sqrt as well.
To address some of your other concerns:
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
You call this "nonsense", so it's clear you don't expect it to work, but why doesn't it? Well, the problem is that (+) has type Num a => a -> a -> a—you can only add two things of the same type. This is generally good, since it means you can't add a complex number to a 5×5 real matrix; however, since 0.0 must be an instance of Fractional, you won't be able to add it to x :: Int.
It seems that (sqrt 500) works fine…
This works because the type of 500 isn't what you expect. Let's ask our trusty companion GHCi:
Prelude> :t 500
500 :: (Num t) => t
In fact, all integer literals have this type; they can be any sort of number, which works because the Num class contains the function fromInteger :: Integer -> a. So when you wrote sqrt 500, GHC realized that 500 needed to satisfy 500 :: (Num t, Floating t) => t (and it will implicitly pick Double for numeric types like that thank to the defaulting rules). Similarly, the 0.0 above has type Fractional t => t, thanks to Fractional's fromRational :: Rational -> a function.
… but (sqrt x) insists on x being a Floating …
See above, where we look at the type of sqrt.
… and there is no function I can find to convert an Int to a real ….
Well, you have one now: fromIntegral. I don't know why you couldn't find it; apparently Hoogle gives much worse results than I was expecting, thanks to the generic type of the function.
Why is this so hard?
I hope it isn't anymore, now that you have fromIntegral.

Haskell types frustrating a simple 'average' function

I'm playing around with beginner Haskell, and I wanted to write an average function. It seemed like the simplest thing in the world, right?
Wrong.
It seems like Haskell's type system forbids average from working on a generic numeric type - I can get it to work on a list of Integrals, or an list of Fractionals, but not both.
I want:
average :: (Num a, Fractional b) => [a] -> b
average xs = ...
But I can only get:
averageInt :: (Integral a, Fractional b) => [a] -> b
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)
or
averageFrac :: (Fractional a) => [a] -> a
averageFrac xs = sum xs / fromIntegral (length xs)
and the second one seems to work. Until I try to pass a variable.
*Main> averageFrac [1,2,3]
2.0
*Main> let x = [1,2,3]
*Main> :t x
x :: [Integer]
*Main> averageFrac x
<interactive>:1:0:
No instance for (Fractional Integer)
arising from a use of `averageFrac ' at <interactive>:1:0-8
Possible fix: add an instance declaration for (Fractional Integer)
In the expression: average x
In the definition of `it': it = averageFrac x
Apparently, Haskell is really picky about its types. That makes sense. But not when they could both be [Num]
Am I missing an obvious application of RealFrac?
Is there way to coerce Integrals into Fractionals that doesn't choke when it gets a Fractional input?
Is there some way to use Either and either to make some sort of polymorphic average function that would work on any sort of numeric array?
Does Haskell's type system outright forbid this function from ever existing?
Learning Haskell is like learning Calculus. It's really complicated and based on mountains of theory, and sometimes the problem is so mindbogglingly complex that I don't even know enough to phrase the question correctly, so any insight will be warmly accepted.
(Also, footnote: this is based off a homework problem. Everybody agrees that averageFrac, above, gets full points, but I have a sneaking suspicion that there is a way to make it work on both Integral AND Fractional arrays)
So fundamentally, you're constrained by the type of (/):
(/) :: (Fractional a) => a -> a -> a
BTW, you also want Data.List.genericLength
genericLength :: (Num i) => [b] -> i
So how about removing the fromIntegral for something more general:
import Data.List
average xs = realToFrac (sum xs) / genericLength xs
which has only a Real constraint (Int, Integer, Float, Double)...
average :: (Real a, Fractional b) => [a] -> b
So that'll take any Real into any Fractional.
And note all the posters getting caught by the polymorphic numeric literals in Haskell. 1 is not an integer, it is any number.
The Real class provides only one method: the ability to turn a value in class Num to a rational. Which is exactly what we need here.
And thus,
Prelude> average ([1 .. 10] :: [Double])
5.5
Prelude> average ([1 .. 10] :: [Int])
5.5
Prelude> average ([1 .. 10] :: [Float])
5.5
Prelude> average ([1 .. 10] :: [Data.Word.Word8])
5.5
The question has been very well answered by Dons, I thought I might add something.
When calculating the average this way :
average xs = realToFrac (sum xs) / genericLength xs
What your code will do is to traverse the list twice, once to calculate the sum of its elements, and once to get its length.
As far as I know, GHC isn't able yet to optimize this and compute both the sum and length in a single pass.
It doesn't hurt even as a beginner to think about it and about possible solutions, for example the average function might be written using a fold that computes both the sum and length; on ghci :
:set -XBangPatterns
import Data.List
let avg l=let (t,n) = foldl' (\(!b,!c) a -> (a+b,c+1)) (0,0) l in realToFrac(t)/realToFrac(n)
avg ([1,2,3,4]::[Int])
2.5
avg ([1,2,3,4]::[Double])
2.5
The function doesn't look as elegant, but the performance is better.
More information on Dons blog:
http://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-at-a-high-altitude-for-low-level-performance/
Since dons has done such a good job at answering your question, I'll work on questioning your question....
For example, in your question, where you first run an average on a given list, getting a good answer. Then, you take what looks like the exact same list, assign it to a variable, then use the function the variable...which then blows up.
What you've run into here is a set-up in the compiler, called the DMR: the D readed M onomorphic R estriction. When you passed the list straight into the function, the compiler made no assumption about which type the numbers were, it just inferred what types it could be based on usage, and then picked one once it couldn't narrow the field down any more. It's kind of like the direct opposite of duck-typing, there.
Anyway, when you assigned the list to a variable, the DMR kicked in. Since you've put the list in a variable, but given no hints on how you want to use it, the DMR made the compiler pick a type, in this case, it picked one that matched the form and seemed to fit: Integer. Since your function couldn't use an Integer in its / operation (it needs a type in the Fractional class), it makes that very complaint: there's no instance of Integer in the Fractional class. There are options you can set in GHC so that it doesn't force your values into a single form ("mono-morphic", get it?) until it needs to, but it makes any error messages slightly tougher to figure out.
Now, on another note, you had a reply to dons' answer that caught my eye:
I was mislead by the chart on the last page of cs.ut.ee/~varmo/MFP2004/PreludeTour.pdf
that shows Floating NOT inheriting properties from Real, and I then assumed that
they would share no types in common.
Haskell does types differently from what you're used to. Real and Floating are type classes, which work more like interfaces than object classes. They tell you what you can do with a type that's in that class, but it doesn't mean that some type can't do other things, any more than having one interface means that a(n OO-style) class can't have any others.
Learning Haskell is like learning Calculus
I'd say learning Haskell is like learning Swedish - there are lots of little, simple things (letters, numbers) that look and work the same, but there are also words that look like they should mean one thing, when they actually mean something else. But once you get fluent in it, your regular friends will be amazed at how you can spout off this oddball stuff that makes gorgeous beauties do amazing tricks. Curiously, there are many folks involved in Haskell from the beginnings, who also know Swedish. Maybe that metaphor is more than just a metaphor...
:m Data.List
let list = [1..10]
let average = div (sum list) (genericLength list)
average
I'm amazed that after all of these years, no one has pointed out that Don Stewart's average doesn't work with complex numbers, while OP's averageFrac does work with complex numbers. Neither one is unambiguously superior to the other.
The fundamental reason why you can't write
average :: (Num a, Fractional b) => [a] -> b
is that it can be instantiated at a type like
average :: [Complex Double] -> Double
Haskell's numeric classes support conversions that are a little bit lossy, like Rational to Double, Double to Float, and Integer to Int, but don't support extremely lossy conversions like complex to real, or fractional to integral. You can't convert Complex Double to Double without explicitly taking (e.g.) the real part of it, which is not something that average should be doing. Therefore, you can't write average :: [Complex Double] -> Double. Therefore, you can't write average with any type that can be specialized to [Complex Double] -> Double.
The most Haskellish type for average is probably OP's averageFrac. Generally, functions that aren't dedicated to type conversion should be leaving the type conversion to the caller as much as possible. averageFrac will work with practically any numeric type, either directly or after coercion of the input list. The caller, being closer to the source of the data, is more likely to know whether it needs to be coerced or not (and if it doesn't know, it can leave the decision to its caller). In contrast, Don Stewart's average just doesn't support complex numbers, even with coercion. You'd either have to rewrite it from scratch or else call it twice with the real and imaginary projections of the list (and then write another wrapper for quaternions that calls it four times, etc.).
Yeah, Haskell's type system is very picky. The problem here is the type of fromIntegral:
Prelude> :t fromIntegral
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral will only accept an Integral as a, not any other kind of Num. (/), on the other hand only accepts fractional. How do you go about making the two work together?
Well, the sum function is a good start:
Prelude> :t sum
sum :: (Num a) => [a] -> a
Sum takes a list of any Num and returns a Num.
Your next problem is the length of the list. The length is an Int:
Prelude> :t length
length :: [a] -> Int
You need to convert that Int into a Num as well. That's what fromIntegral does.
So now you've got a function that returns a Num and another function that returns a Num. There are some rules for type promotion of numbers you can look up, but basically at this point you're good to go:
Prelude> let average xs = (sum xs) / (fromIntegral (length xs))
Prelude> :t average
average :: (Fractional a) => [a] -> a
Let's give it a trial run:
Prelude> average [1,2,3,4,5]
3.0
Prelude> average [1.2,3.4,5.6,7.8,9.0]
5.4
Prelude> average [1.2,3,4.5,6,7.8,9]
5.25

Resources