如何避免"异常:Prelude.head:空列表"? - 哈斯克尔

Tri*_*yen 4 haskell list

大家晚上好,我是哈斯凯尔的新手.我试图总结一个读取字符串Unicode值的列表,并将它们存储在一个列表中,然后将整数加起来.

 getLetterUnicodeValue :: Char -> Int
 getLetterUnicodeValue l = (ord l) - 64

 unicodeValueList :: String -> [Int]
 unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x)

 total :: [Int] -> Int
 total []     = 0
 total x = (head x) + (total (tail x))
Run Code Online (Sandbox Code Playgroud)

当字符串到达​​最后一个字符并且总结功能无法成功执行时,我得到了空列表的错误.有什么办法可以在功能unicodeValueList结束时停止它.

*** Exception: Prelude.head: empty list
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 6

避免此异常的最可靠方法是不使用head.相反,您可以使用模式匹配来获取列表的头部和尾部:

unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs

total (x:xs) = x + total xs
Run Code Online (Sandbox Code Playgroud)

这种方式xxs将只可当列表不为空,并可以保证你永远不小心访问一个空列表的头部或尾部.

当然,现在您将收到模式匹配不完整的警告:您没有指定列表为空时应该发生什么.当然,之前也是如此,但是现在您使用模式匹配,编译器实际上可以看到它并警告您(而前一代码在运行时崩溃而没有任何预先警告).

那么当列表为空时应该怎么做?好吧,空字符串不包含unicode值,对吧?所以它应该在输入为空时返回空列表:

unicodeValueList [] = []
Run Code Online (Sandbox Code Playgroud)

当然,您不需要模式匹配来修复错误.你可以使用一个if来确保你只调用head,tail当列表不为空时.但是,如果您这样做,编译器将无法验证您的检查是否有序.如果您使用模式匹配并完全避免不安全headtail函数,您将永远无法意外访问空列表的头部或尾部,如果您忘记考虑列表可能为空,编译器将发出警告.