Haskell错误:非详尽的模式

时间:2017-09-27 10:04:19

标签: haskell

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

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

每当我输入一个句子时,我都会收到一条错误,上面写着“函数cwords中的非详尽模式”。空字符串工作正常。 (我对Haskell很新)

1 个答案:

答案 0 :(得分: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不是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