0
votes

I'm very new to Haskell and I'm trying to make a basic function which finds the mean of a list. I've almost got it solved, except for the last bit of division I have to do.

randInts = take 5 $ randoms (mkStdGen 11) :: [Int]

listSum :: (Num a) => [a] -> a
listSum [] = 0
listSum (x:xs) = x + listSum xs

listLength :: (Num a) => [a] -> a
listLength [] = 0
listLength (x:xs) = 1 + listLength xs

listMean :: (Num a) => [a] -> a
listMean [] = 0
listMean x = (listSum x) / (listLength x)

This is what I started with, where listSum and listLength basically have the same functionality as the sum and length operators on lists respectively and listMean takes those two and divides them. When I run this, however, I get an error saying "Could not deduce (Fractional a) arising from a use of ‘/’ from the context: Num a"

At first, I just thought I had used the wrong type and switched listMean to start with listMean :: (Fractional a) => [a] -> a. This allowed me to compile, but when I attempted to run it by giving it randInts, but instead I got the error message "No instance for (Fractional Int) arising from a use of ‘listMean’."

I am not sure what I am missing here. Could I have some advice please?

2
You mean removing fractional? I did that and it gave me an error saying "Expected a type, but ‘a’ has kind ‘Constraint’"remington howell
That gives me the error "No instance for (Fractional Int) arising from a use of ‘listMean’"remington howell

2 Answers

2
votes

At a guess: you are testing this in ghci with listMean randInts. This is a problem, because Int doesn't support division via (/) but rather supports integer division via div (to avoid a certain class of bugs that crops up in languages that conflate the two).

You have a two obvious choices, namely, convert your Ints to something that does support division (e.g. Double) or generate random Doubles in the first place.

listMean (map fromIntegral is) :: Double
listMean . take 5 . randoms $ mkStdGen 11 :: Double

By the way, if my guess is correct: in the future, you should really include all the details of the things you did, in so much detail that we playing along at home could follow them and see the exact same error; and you should include the entire content of the error, especially since in this case it mentions the code snippet that caused it and would have made diagnosis instantaneous.

1
votes

The problem is that:

(Num a) => [a] -> a

Applied with [Int], both listSum and listLength returns Int, which does not support /. You need to convert the return values before division:

listMean :: (Num a, Integral a) => [a] -> Double
listMean [] = 0
listMean x = (fromIntegral $ listSum x) / (fromIntegral $ listLength x)