3

我正在尝试编写一个加载 2 个文本文件的程序,将这些文件中的数字转换为 2 个列表,然后计算这些列表之间的 pearson 相关性。

pearson 函数只能接受浮点数,所以我制作了一个名为 floatconvert 的函数来尝试解决这个问题,但它没有。我收到一条错误消息,提示“无法将预期类型 'IO b0' 与实际类型 'Float' 匹配。” 在‘pearson’的第一个参数中,即‘input1.’”

任何解决此问题的帮助将不胜感激。

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 ])
4

1 回答 1

10

在这种情况下,错误消息有些误导。真正的问题是pearson不返回IO something。如果您打算打印结果,请写

main = do
    ...    
    print $ pearson input1 input2

GHC 在这里混淆的原因是 pearson 的推断类型是

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

因此,当您尝试将其用作 do-block 中的语句时,它会从返回类型推断出a ~ IO b,因此参数必须具有 type [IO b]。但是,它已经知道它们具有类型,因此当问题的根源是返回类型时,[Float]您会收到一条关于它无法在参数中匹配的令人困惑的错误消息FloatIO b

我赞同 Dave 关于向函数添加类型签名的建议。它可以使错误消息更有帮助。例如,如果您给出pearson了类型签名pearson :: [Float] -> [Float] -> Float,您将收到以下消息:

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
于 2012-10-12T16:15:38.203 回答