2017-09-27 31 views
1

我正在尝试编写一个函数来计算句子中的单词。Haskell错误:非穷举模式

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

每当我输入一个句子时,我都会收到一个错误,说“函数cwords中的非穷举模式”。一个空字符串正常工作。 (我很新哈斯克尔)

+0

如果该字符串有一个字符? –

+0

谢谢!你是对的。我在想是isAlpha b == False覆盖那一个。 – batlord

回答

5

的问题是,你定义两个条款:

  • 一个与空列表

    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不​​,那么我们就必须在(b:c)执行递归在这里,但可以直接在c执行递归;和
  • 我们可以将otherwise大写字母重写为处理至少包含一个元素的列表的子句。

所得为:

相关问题