大家晚上好,我是哈斯凯尔的新手。我试图总结一个读取字符串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))
当字符串到达最后一个字符并且总结功能无法成功执行时,我得到了空列表的错误。有什么办法可以在函数unicodeValueList
结束时停止它。
*** Exception: Prelude.head: empty list
答案 0 :(得分:5)
避免此异常的最可靠方法是不使用head
。相反,您可以使用模式匹配来获取列表的头部和尾部:
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
total (x:xs) = x + total xs
这种方式x
和xs
只有在列表非空时才可用,并且保证您不会意外地访问空列表的头部或尾部。
当然,现在您会收到一个警告,指出模式匹配不完整:您没有指定列表为空时应该发生什么。当然,在此之前也是如此,但是现在您使用模式匹配,编译器实际上可以看到它并向您发出警告(而前一代码在运行时崩溃而没有任何预先警告)。
那么当列表为空时应该怎么做?好吧,空字符串不包含unicode值,对吧?所以它应该在输入为空时返回空列表:
unicodeValueList [] = []
当然,您不需要模式匹配来修复错误。您可以使用if
确保在列表不为空时只调用head
和tail
。但是如果你这样做,编译器就无法验证你的检查是否有序。如果您使用模式匹配并完全避免不安全的head
和tail
函数,您将永远无法意外访问空列表的头部或尾部,编译器将警告您,如果您永远不要忘记列表可能是空的。
答案 1 :(得分:2)
是的,您只需要在unicodeValueList
unicodeValueList :: String -> [Int]
unicodeValueList [] = []
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
请注意,这可以更好地编写为unicodeValueList = map getLetterUnicodeValue
。你得到head
错误的原因是你的递归没有基本情况 - 它一直试图递归,即使它已经到达空列表。