【问题标题】:Haskell - Non-exhaustive patterns in functionHaskell - 功能中的非详尽模式
【发布时间】:2014-10-06 20:31:59
【问题描述】:

以下函数的重点是接收一个列表并将列表拆分为 2 个列表的元组。第一个列表将维护偶数索引项,第二个将维护奇数索引项。 “Pos”是当前的位置。 (0 正在函数调用中传递)。传入的列表的初始元组是 ([],[])

split :: [Integer] -> ([Integer],[Integer]) -> Integer -> ([Integer], [Integer])
split [] (x,y) _ = (x,y)
split (x:xs) ((y:ys),(z:zs)) pos
    | pos `mod` 2 == 0  = doSplit xs ((y:ys) ++ [x], (z:zs)) (pos + 1)
    | otherwise         = doSplit xs ((y:ys), (z:zs) ++ [x]) (pos + 1)

Haskell 正在报告

*** Exception: split.hs:(113,1)-(116,73): Non-exhaustive patterns in function split

我理解它认为我没有涵盖应该涵盖的“某些情况”,但是我觉得我已经涵盖了所有情况。

如果列表为空 -> 返回传入的列表元组 否则 -> 将 x 添加到列表之一并在 xs 上递归。

从我的角度来看,这个函数是严格递减的,直到 xs 变为 [] 在这种情况下它会停止。

我错过了什么吗?

【问题讨论】:

  • 如果列表不为空,但您的元组包含一个空列表会怎样?
  • 您可以使用even pos 代替pos `mod` 2 == 0。 (我知道这不能解决您的问题,但 Zeta 可以)
  • 没关系,函数不会在元组上递归。 [] ++ [x] 不是有效语句吗?事实上,这应该几乎总是如此,因为传入的元组实际上是空的。有没有办法让我指定我希望它在两种情况下都进行递归?

标签: list haskell tuples


【解决方案1】:

当第一个列表非空但元组参数中的一个(或两个)列表为空时不匹配,例如

split [1] ([], [])

但是您的第二个子句似乎并不要求元组中的任何一个列表都是非空的,因此您可以将其更改为:

split (x:xs) (ys,zs) pos
    | pos `mod` 2 == 0  = doSplit xs (ys ++ [x], zs) (pos + 1)
    | otherwise         = doSplit xs (ys, zs ++ [x]) (pos + 1)

【讨论】:

  • 谢谢!我想我没有意识到 (y:ys) 推断出一个缺点,而不仅仅是“那里有什么”
  • @Aserian : 实际上是列表的两个构造函数之一,另一个是[]。您可以也应该像对待任何其他要进行模式匹配的构造函数一样对待它。
  • @Aserian 匹配任何列表的模式是ystype 表示它是一个列表;您不需要在变量中使用任何特殊符号来指示它是一个列表。 y:ys 只能是“某物被赋予某物”;无论您为yys 选择什么值,该表达式都不可能最终等于[]
猜你喜欢
  • 1970-01-01
  • 2018-09-06
  • 2021-11-30
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多