Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pearson Correlation with Haskell Float Type Conflict

I'm trying to write a program that loads 2 text files, converts the numbers in those files into 2 lists, and then calculates the pearson correletion between those lists.

The pearson function can only take floats, so I made a function called floatconvert to try to fix this problem, but it hasn't. I get an error saying "Couldn't match expected type 'IO b0' with actual type 'Float.' In the first argument of 'pearson', namely 'input1.'"

Any help with fixing this problem would be greatly appreciated.

main = do
    input1file <- readFile "input1.txt"
    input2file <- readFile "input2.txt"

    let input1 = floatconvert input1file
    let input2 = floatconvert input2file

    pearson input1 input2

floatconvert x = [ read a::Float | a <- words x ]

pearson xs ys = (psum-(sumX*sumY/n))/(sqrt((sumXsq-(sumX**2/n)) * (sumYsq-(sumY**2/n))))
    where
        n = fromIntegral (length xs)
        sumX = sum xs
        sumY = sum ys
        sumXsq = sum([ valX*valX | valX <- xs ])
        sumYsq = sum([ valY*valY | valY <- ys ])
        psum = sum([ fst val * snd val | val <- zip xs ys ])
like image 593
subtlearray Avatar asked Aug 02 '26 21:08

subtlearray


1 Answers

The error message is somewhat misleading in this case. The real problem is that pearson does not return IO something. If you meant to print the result, write

main = do
    ...    
    print $ pearson input1 input2

The reason for GHC's confusion here is that the inferred type of pearson is

pearson :: Floating a => [a] -> [a] -> a

so when you try to use it as a statement in the do-block, it infers from the return type that a ~ IO b and therefore the arguments must have type [IO b]. However, it already knows that they have type [Float] so you get a confusing error message about it being unable to match Float with IO b in the argument when the source of the problem is the return type.

I second Dave's advice about adding type signatures to your functions. It can make error messages more helpful. For example, if you had given pearson the type signature pearson :: [Float] -> [Float] -> Float, you would have gotten this message:

Pearson.hs:8:5:
    Couldn't match expected type `IO b0' with actual type `Float'
    In the return type of a call of `pearson'
    In a stmt of a 'do' block: pearson input1 input2
like image 160
hammar Avatar answered Aug 05 '26 15:08

hammar