Haskell无法匹配奇怪的预期类型

时间:2019-11-21 16:00:06

标签: list haskell types

我有一个列表[(String, [(String, Float)],想要计算浮点数的平均值,以便得到结果[(String, Float)]。您将了解阅读代码。

type StudentName = String
type CourseName  = String
type ExamScore   = (CourseName, Float)
type StudentData = [(StudentName, [ExamScore])]

--Delete duplicated entries
filterDuplicates :: StudentData -> StudentData
filterDuplicates [] = []
filterDuplicates sd = [(head sd)] ++ filterDuplicates(filter (\ x -> x /= (head sd)) (tail sd))

--Delete entries whose score is not in scope or whose are not listed the list of course names
filterValidEntries :: [ExamScore] -> [CourseName] -> [ExamScore]
filterValidEntries es cn = filter (\ x -> ((fst x) `elem` cn) && ((snd x) >= 1.0 && (snd x) <= 5.0)) es

--Calulate the average of the cleared data
calculateAverages :: StudentData -> [CourseName] -> [(StudentName, Float)]
calculateAverages sd cn = map createTupel (filterDuplicates sd)
    where createTupel x = ((fst x), ((foldr (+) 0 (snd(filterValidEntries(snd x) cn))) / fromIntegral(length (filterValidEntries(snd x) cn))))

尝试编译此错误,出现以下错误:

    * Couldn't match expected type `(a0, t0 b)'
                  with actual type `[ExamScore]'
    * In the first argument of `snd', namely
        `(filterValidEntries (snd x) cn)'
      In the third argument of `foldr', namely
        `(snd (filterValidEntries (snd x) cn))'
      In the first argument of `(/)', namely
        `(foldr (+) 0 (snd (filterValidEntries (snd x) cn)))'
    * Relevant bindings include
        createTupel :: (a, [ExamScore]) -> (a, b)
          (bound at C:\\Users\Lennart\sciebo\Semster 1\Info\Übungen\Übung 06\WI0
4_B06_A04_G01.hs:72:15)
   |
72 |         where createTupel x = ((fst x), ((foldr (+) 0 (snd(filterValidEntri
es(snd x) cn))) / fromIntegral(length (filterValidEntries(snd x) cn))))
   |                                                            ^^^^^^^^^^^^^^^^
^^^^^^^^^^^^

希望您能帮助我,谢谢。

1 个答案:

答案 0 :(得分:3)

对风格的评论很微不足道,但很重要。 Haskell函数应用程序从不编写为f(x+y)f(之间没有空格。它总是写为f (x+y)

无论如何,这是找出此错误消息的方法。重要的一点是,GHC期望使用(a, t b)形式的类型-atb的重要性不如它期望的元组( (例如,pair)类型,但是给了[ExamScore],显然是列表,而不是期望的元组。

这是哪里发生的?嗯,正如错误消息所言,问题发生在尝试将第一个参数传递给snd时,即(filterValidEntries (snd x) cn)

请注意,snd由于抓住了一个元组的第二个元素,显然期望。但是,参数filterValidEntries (snd x) cn不返回元组,它实际上返回列表[ExamScore]

那是你的问题。您是否真的打算将返回列表的参数filterValidEntries (snd x) cn传递给需要元组的函数snd?不,你没有。您想做什么 ?也许将snd映射到列表的每个元素?