【问题标题】:Haskell error: non-exhaustive patternsHaskell 错误:非详尽模式
【发布时间】:2017-09-27 10:04:19
【问题描述】:

我正在尝试编写一个函数来计算句子中的单词。

cwords :: String -> Int
cwords "" = 0
cwords (a:b:c)
    |isAlpha a && (isAlpha b == False) = 1 + cwords (b:c) 
    |otherwise = cwords (b:c)

每当我输入一个句子时,我都会收到一个错误提示“函数 cwords 中的非详尽模式”。空字符串可以正常工作。 (我对 Haskell 很陌生)

【问题讨论】:

  • 如果字符串只有一个字符怎么办?
  • 谢谢!你是对的。我在想 isAlpha b == False 覆盖了那个。

标签: haskell


【解决方案1】:

问题是你定义了两个子句:

  • 一个空列表

    cwords "" = 0
    
  • 其中一个列表包含至少两个元素:

    cwords (a:b:c) = ...
    

因此,Haskell 表示它不知道在字符串只包含一个字符的情况下该怎么做,因为没有子句指定在这种情况下该怎么做。

由于您计算单词,如果我们获得最后一个字符,我们应该将其计为一个单词(假设它是一个字母字符)。所以代码应该是:

cwords :: String -> Int
cwords "" = 0
cwords (a:b:c)
    |isAlpha a && (isAlpha b == False) = 1 + cwords (b:c) 
    |otherwise = cwords (b:c)

到:

cwords :: String -> Int
cwords "" = 0
cwords [_] | isAlpha a = 1
cwords (a:b:c)
    |isAlpha a && (isAlpha b == False) = 1 + cwords (b:c)
    | otherwise = cwords (b:c)

话虽如此,我们仍然可以改进代码:

  • 我们可以用not (isAlpha b)代替isAlpha b == False
  • 如果我们知道b不是isAlpha,那么这里就不必对(b:c)进行递归,而是可以直接对c进行递归;和
  • 我们可以将otherwise 的情况重写为一个处理包含至少一个元素的列表的子句。

导致:

cwords :: String -> Int
cwords "" = 0
cwords [a] | isAlpha a = 1
cwords (a:b:c) |isAlpha a && not (isAlpha b) = 1 + cwords c
cwords (_:b) = cwords b

【讨论】:

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