【问题标题】:Haskell: non-exhaustive-patternsHaskell:非穷举模式
【发布时间】:2014-09-26 07:16:04
【问题描述】:

我正在为明天的测试进行培训,以完成我对函数式编程的介绍,但有一件事我不明白。

每当我有这样的程序时:

test [] = []
test (x:xs) = test (xs)

他所做的是从列表中取出第一个元素并继续其余的。只要只剩下一个,xs 就应该是[],这反过来又会触发test [] = []。但是每当我运行这个算法时,我都会得到一个错误。 Exception: <interactive>:20:5-16: Non-exhaustive patterns in function test.

我在网上找不到明确的解释。有人可以给我一个链接,其中解释清楚或向我解释吗?

【问题讨论】:

  • 很奇怪。您发布的代码 sn-p 不包含非详尽的模式。
  • 只是在黑暗中拍摄:您是否可能试图将这个定义输入到 ghci 中?如果是这样,您应该使用单个 let 语句:let test [] = [] ; test (x:xs) = test xs
  • 是的,这就是我正在做的。非常感谢。我已经开始吓坏了,因为我花了整整一周时间编写递归,但我不明白为什么这个不起作用。
  • 就个人而言,我更喜欢在文件中编写代码并加载到 ghci 中。这是一个很好的例子,说明了为什么你应该这样做。它会通过一个不明显的解决方案来避免这个问题。

标签: haskell ghci non-exhaustive-patterns


【解决方案1】:

您在问题正文中发布的代码确实进行了详尽的模式匹配。但是,如果您尝试将此定义输入 ghci,则应使用 single let 语句:

Prelude> let test [] = [] ; test (x:xs) = test xs

你在做什么here 不正确。您首先定义了一个非穷举函数test

Prelude> let test [] = []

然后你定义另一个非穷举函数,也称为test,它隐藏了第一个:

Prelude> let test (x:xs) = test xs

【讨论】:

    【解决方案2】:

    在 Haskell 的 REPL (GHCi) 中尝试婴儿程序确实是一件非常棘手的事情。

    使用let 不是很明显(尤其是因为在单独的“脚本/程序”中不需要它)。

    有时我们不想创建一个完整的文件,而是尝试一个带有不同“案例”的小函数。

    另一个有用的方法是使用分隔符 :{:} 来定义我们函数的范围。

    假设我们想尝试一个简单的递归sum 函数,它可以添加一个数字列表。然后我们会说:

    λ > :{
    Prelude| sum [] = 0
    Prelude| sum (x:xs) = x + sum xs
    Prelude| :}
    sum :: Num t => [t] -> t
    Prelude
    λ > sum [1..10]
    55
    it :: (Enum t, Num t) => t
    

    请注意,我们现在可以很好地看到我们的功能范围!

    希望这会有所帮助。干杯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      相关资源
      最近更新 更多