我正在关注教程。 (真实世界Haskell)
我有一个关于在空列表上调用的头部和尾部的初学者问题:在GHCi中它返回异常。
直觉上我想我会说他们都应该返回一个空列表。你能纠正我吗?为什么不 ? (据我记得在OzML中左侧或右侧的空列表返回nil)
我肯定还没有在教程中讨论过这个主题,但它不是bug的来源(如果不提供参数)? 我的意思是,如果传递给函数的参数列表可能是可选的,那么用head读取它们可能会导致错误?
我只知道GHCi的行为,我不知道编译时会发生什么。
答案 0 :(得分:13)
直觉上我认为他们都应该返回一个空列表。你能纠正我吗?为什么不呢?
嗯 - head
是[a] -> a
。它返回单个第一个元素;没有清单。
当空列表中没有第一个元素时?那又回来了什么?您无法从零创建a
类型的值,因此剩下的只有undefined
- 错误。
tail
?尾部基本上是没有第一个元素的列表 - 即比原始元素短一个项目。没有第一要素时,你不能坚持这些法律。
当您从盒子中取出一个苹果时,您不能拥有相同的盒子(tail [] == []
时发生的事情)。行为也必须是undefined
。
这导致以下结论:
我肯定还没有在教程中介绍过这个主题,但它不是bug的来源吗?我的意思是,如果传递给函数的参数列表可能是可选的,那么用head读取它们可能会导致错误?
是的,它是bug的来源,但因为它允许编写有缺陷的代码。基本上试图读取不存在的值的代码。所以:*不要使用头/尾** - 使用模式匹配。
sum [] = 0
sum (x:xs) = x + sum xs
编译器可以guarantee涵盖所有可能的情况,始终定义值并且阅读起来更清晰。