Haskell中列表上的模式匹配失败

时间:2013-03-26 13:48:44

标签: list design-patterns haskell match

我刚刚开始使用Haskell,偶然发现了一个问题。 根据Haskell的说法,我有一个模式匹配失败,但我没有看到如何。 这是我尝试执行的代码:

statistics ::   [Int] -> (Int, Int, Int)
statistics [gradelist] = ( amountParticipants, average, amountInsufficient)
                        where
                            amountParticipants= length [gradelist]
                            average= sum[gradelist] `div` amountParticipants
                            amountInsufficient= length [number| number<- [gradelist], number<6]

我将'统计'称为:

statistics[4,6,4,6]

这导致模式匹配失败,而我期望看到:(4,5,2)

statistics[6]

给出答案:(1,6,0)(这是正确的)。 有人能告诉我为什么我的第一个电话会导致这种模式匹配?因为我很确定我将列表作为参数

3 个答案:

答案 0 :(得分:7)

如果你写statistics [gradelist] = ...,你就会对包含一个被称为gradelist的唯一元素的单身列表进行模式匹配。因此,您的函数仅定义为长度恰好为1的列表(例如[6]);对于空列表([])或包含两个或更多元素的列表(例如[4,6,4,6]),它未定义。

您的函数的正确版本将为

statistics :: [Int]     -> (Int, Int, Int)
statistics    gradelist =  (amountParticipants, average, amountInsufficient)
  where
    amountParticipants = length gradelist
    average            = sum gradelist `div` amountParticipants
    amountInsufficient = length [number| number <- gradelist, number < 6]

正如@thoferon所说,你还需要对gradelist为空的情况作出特殊安排,以免在计算average时除以零。

答案 1 :(得分:2)

如上所述,只需将[gradelist]替换为gradelist。此外,您可能希望使用[]匹配空列表,以避免在average中除以零,如:

statistics [] = (0,0,0)

答案 2 :(得分:1)

模式中的列表语法[ ]解构列表。模式[gradelist]匹配一个只包含一个值的列表,并命名列表gradelist中的值。如果您尝试使用包含四个值的列表调用该函数,则会出现模式匹配失败。

要匹配值而不解构它,请使用变量作为模式。