【问题标题】:Pattern match(es) are non-exhaustive模式匹配并非详尽无遗
【发布时间】:2026-02-22 07:40:01
【问题描述】:

我正在尝试创建一个函数,以 multiples x [y] 的形式从整数列表中消除给定整数的倍数,其中 x 是给定整数,y 是列表。

这是我所拥有的:

multiples :: Integer -> [Integer] -> [Integer]
multiples a [] = []
multiples a [b] = filter (\l -> l `mod` a /= 0) [b]

multiples 在调用时会失败,说“函数倍数中的非详尽模式”。所以我在我的文件中使用了ghci -Wall 来查看缺少哪些模式,它会返回:

multiples.hs:2:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for `multiples': Patterns not matched: _ (_:_:_)

multiples.hs:2:11: warning: [-Wunused-matches]
    Defined but not used: `a'

我觉得我在第 2 行中遗漏了一些非常简单的东西,但我有点卡住了。我做错了什么?

【问题讨论】:

    标签: haskell pattern-matching non-exhaustive-patterns


    【解决方案1】:

    欢迎来到堆栈溢出!在你的函数中有几件事需要修复,但我将从你似乎最困惑的那件事开始:这里 [b] 是一个匹配 one-element 列表的模式,将其命名为单品b。 ([b, c] 将是匹配二元素列表的模式,等等。)它不是匹配任意长的bs 列表的模式。 GHC 告诉你,因为你没有考虑到函数被赋予两个或更多元素列表的情况。

    如果您想匹配bs 的任意列表,请省略方括号。此外,您的函数的第一行不是必需的,因为第二行已经处理了这种情况。

    multiples :: Integer -> [Integer] -> [Integer]
    multiples a bs = filter (\b -> b `mod` a /= 0) bs
    

    或者,使用列表推导式,

    multiples :: Integer -> [Integer] -> [Integer]
    multiples a bs = [b | b <- bs, b `mod` a /= 0]
    

    还有两件事:我将这个函数命名为 withoutMultiples,因为它过滤掉 a 的倍数,并且因为默认情况下 Haskell 函数是柯里化的,所以你可以省略 bs filter 版本。

    withoutMultiples :: Integer -> [Integer] -> [Integer]
    withoutMultiples a = filter (\b -> b `mod` a /= 0)
    

    【讨论】:

    • 感谢您的帮助 - 我在这里复制代码时错过了=。将[b] 的两个实例更改为bs 解决了这个问题!
    【解决方案2】:

    你的模式

        multiples a [b]
    

    需要一个整数(绑定到名称“a”)和包含一个元素的整数列表(绑定到名称“b”)。删除此模式中的方括号(这会将“b”的类型更改为 [Integer]),它应该可以工作。你也可以curry这个函数来形成

        multiples a = filter (\l -> l `mod` a /= 0)
    

    并省略第一个模式,因为它应该被过滤器功能覆盖。

    【讨论】:

    • 感谢您的回答 - 我错过了 [b] 暗示一个元素列表。用bs 替换它确实解决了这个问题。由于对非详尽模式错误进行故障排除而添加了第一个模式。
    • 有趣的事实 - 可以以无点样式编写该函数,如下所示 multiples = filter . ((/=) 0 .) . flip mod 有时查看它并尝试理解所有转换是一个很好的练习。