Haskell以安全语言而闻名。通常会将更多可能的编程错误推送到编译时错误,并减少运行时间。
这方面的一个例子是if
表达式。 if中的else
始终是强制性的。你需要掩盖两种可能性。这很好,因为您已经考虑并涵盖了运行时将发生的所有可能性。
现在Haskell有一个case
表达式。 (这与其他OO和命令式语言中的switch
语句有一些相似之处 - 但Haskell在类型系统中增加了很多丰富性。
describeList :: [a]
describeList xs = "The list is " ++ case cs of [] -> "empty."
[x] -> "a singleton list."
xs -> "a longer list."
但是使用case
表达式,默认的'catch-all'不是必需的。
对我而言,这听起来会导致运行时错误。
我的问题是:为什么默认的catch-all在Haskell case
语句中不是强制性的?
答案 0 :(得分:7)
Haskell肯定比其他语言更安全更安全,尤其是主流语言,但它远非100%安全。 Haskell中的其他不安全功能包括编写无限循环的功能,如let x = x in x
或unsafePerformIO
,error
或undefined
。我想你可以说这只是方便和安全之间的权衡。
在比简单示例更复杂的代码中,有时会出现一些您知道不会发生的情况,因此您将它们排除在case
表达式之外,但Haskell的类型系统不够强大编译器能够知道那些丢失的案例是不可能的。 (例如,您可能正在计算一些只能返回数字3
,4
或5
的数学函数,但这个事实是由于您碰巧知道的一些困难定理并且编译器不知道。)
对于它的价值,您可以将-fwarn-incomplete-patterns
传递给ghc
编译器,以便在编译时错过case语句中的分支(如果您愿意)。这包含在-W
选项中,可以打开几个常见的编译器警告。
答案 1 :(得分:4)
并不总是需要一个包罗万象的东西。如果明确处理所有情况(模式匹配穷举),则永远不会达到全部案例。
我可以想到一个强制性捕获所有情况的严重缺点:如果扩展ADT(代数数据类型),依赖代码仍然会编译,程序员不会被提醒他们应该处理的额外情况。