【问题标题】:Non-exhaustive patterns with syntactic sugar and pattern matching具有语法糖和模式匹配的非详尽模式
【发布时间】:2021-03-28 15:20:48
【问题描述】:

我编写了函数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]

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

我在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 的模式时,为什么会出现此错误?

【问题讨论】:

  • fun1 未为非空列表定义(fun2 也未定义。
  • 是的,但假设一个人只会调用fun1fun2 并使用非空列表仍然问题出在fun' ,或者我错过了什么?当然我可以添加fun1 [] = [],但这并不能解决我的问题。
  • fun' 也一样:你只在第二个参数非空时才定义这个,所以 case z 没有意义:你在 (x:xs) 上进行模式匹配
  • 是的:如果所有子模式也匹配,则该模式将“触发”。
  • 像这样反复使用last++ [foo] 很昂贵。而是直接开始发射值,如fun1 (l:ls) = fun' l ls where fun' a [] = []; fun' a (x:xs) = if x &lt; a then x : fun' x xs else fun' a xs

标签: haskell pattern-matching


【解决方案1】:

表达式:

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

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

因此,您可以将其重写为:

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

对于给定的样本输入,返回:

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

【讨论】:

  • 谢谢!我将专注于使用这种语法糖@(x:xs),所以我完全被蒙蔽了。首先,我定义了第二个fun' a [] = a,但您的解决方案当然要干净得多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多