具有语法糖和模式匹配的非详尽模式

Non-exhaustive patterns with syntactic sugar and pattern matching

我编写了函数 fun1,它接受一个列表并删除大于或等于之前数字的每个数字。

fun1 (l:ls) =
    fun' [l] ls
  where
    fun' a z =
      case z of
        []  -> a
        _   -> fun' (if (head z) < (last a) then a ++ [head z] else a) (tail z)

效果很好:

> fun1 [4,4,5,9,7,4,3,1,2,0]
=> [4,3,1,0]

在最后一行中,我想使用 z@(x:xs) 而不是使用 head ztail z,这是我见过一次的语法糖。

我在 fun2 中尝试过,但出现非详尽模式错误。 当我使用 case xs of 而不是 case z of 时,该函数运行时不会抛出错误,但那样它要么跳过最后一个元素,要么我将不得不再次编写操作以应用于最后一个元素(我显然不想做)。

fun2 (l:ls) =
    fun' [l] ls
  where
    fun' a z@(x:xs) =
      case z of -- "case xs of" would work, but will skip the last element
        []  -> a
        _   -> fun' (if x < (last a) then a ++ [x] else a) xs

这会导致非详尽模式错误:

> fun2 [4,4,5,9,7,4,3,1,2,0]
*** Exception: main.hs:(4,5)-(7,61): Non-exhaustive patterns in function fun'

当我尝试匹配 z 的模式时,为什么会出现此错误?

表达式:

fun' a z<b>@(x:xs)</b>> =
    case z of -- "case xs of" would work, but will skip the last element
        <b>[]</b>  -> a
        _   -> fun' (if x < (last a) then a ++ [x] else a) xs

没有多大意义,这意味着如果 z 是一个非空列表,子句只会“触发”,所以 [] -> … 永远不会触发,因为模式 (x:xs) 已经将子句限制为非空列表。

因此您可以将其重写为:

fun' a z =
    case z of
        []     -> a
        <b>(x:xs)</b> -> fun' (if x < (last a) then a ++ [x] else a) xs

对于给定的样本输入,这个 returns:

Prelude> fun2 [4,4,5,9,7,4,3,1,2,0]
[4,3,1,0]