Home Articles

模式匹配并非详尽无遗

Asked
Viewed 1094 times
3

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

这就是我所拥有的:

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

调用 multiples 会失败,说"Non-exhaustive patterns in function 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行非常简单的东西,但我有点卡住了 . 我究竟做错了什么?

2 Answers

  • 4

    欢迎来到Stack Overflow!在你的函数中有几个要修复的东西,但我会从你看起来最困惑的那个开始:这里 [b] 是一个匹配单元素列表的模式,命名它的单个项目 b . ( [b, c] 将是匹配双元素列表的模式,等等 . )它不是匹配任意长的 b 列表的模式 . GHC告诉你,因为你还没有考虑到函数被赋予了两个或更多元素列表的情况 .

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

    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函数是curry,所以你可以省略 filter 版本中的 bs .

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

    你的模式

    multiples a [b]
    

    期望一个Integer(绑定名称为“a”)和包含一个元素(绑定到名称“b”)的Integer列表 . 在此模式中删除方括号(将“b”的类型更改为[Integer]),它应该正常工作 . 你也可以把这个函数用来形成

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

    并省略第一个模式,因为它应该被过滤函数覆盖 .

Related