Haskell error: non

I'm trying to write a function that will count the words in a sentence.

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

I keep getting an error saying "non-exhaustive patterns in function cwords" whenever I enter a sentence. An empty string works fine. (I'm very new to Haskell)


The problem is that you define two clauses:

  • one with the empty list

    cwords "" = 0
    
  • and one where the list contains at least two elements:

    cwords (a:b:c) = ...
    
  • So the Haskell says that it does not know what to do in case the string contains exactly one character, since there is no clause that specifies what to do in that case.

    Since you count words, in case we obtain the last character, we should count this as a word (given it is an alpha-character). So the code should read:

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

    to:

    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)
    

    That being said, we can still improve the code:

  • we can use not (isAlpha b) instead of isAlpha b == False ;
  • if we know b is not isAlpha , then we do not have to perform recursion on (b:c) here, but can directly perform recursion on c ; and
  • we can rewrite the otherwise case as a clause that handles lists with at least one element.
  • Resulting into:

    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
    
    链接地址: http://www.djcxy.com/p/43284.html

    上一篇: 详尽的模式错误haskell

    下一篇: 哈斯克尔错误:非