我已经创建了一个函数,我可以使用(据我所知)案例表达或守卫。
foo a b c = case a of 1 -> [...]
2 -> [...]
3 -> [...]
[...]
otherwise -> error "..."
或
foo a b c | a == 1 = [...]
| a == 2 = [...]
| a == 3 = [...]
| [...]
| otherwise = error "..."
所以,问题是:那两个(案件或警卫)中的哪一个是“更好”的编码?两者基本相同吗?
答案 0 :(得分:13)
第一个被认为是更好的风格,原因有两个。
首先:很多人会说它看起来更好,因为你不必输入所有的==
。当然,这是一个非常主观的原因。此外,您通常不会引入新的case语句,只是匹配函数参数列表中的参数,如下所示:
foo 1 b c = ... -- etc
...
foo _ b c = ... -- for the "otherwise" part
这使得代码更加紧凑和易读,很多人都喜欢。
其次,实际上存在语义差异。想象一下,你有这样的数据类型:
data Cake = Apple | Cheese | Cream
如果使用第一种方法,则匹配case..of
表达式中的构造函数:
case a of
Apple -> "fruit"
_ -> "not fruit"
但是,如果你试图做某种有保障的表达,比如:
| a == Apple = "fruit"
| otherwise = "not fruit"
...它确实无法正常工作,因为Cake
类型没有Eq
个实例,因此您无法使用==
比较两个值。在数据定义之后引入Eq
实例(在deriving (Eq)
之后)并不总是需要,因此在这种情况下不必执行此操作可能很重要。
答案 1 :(得分:9)
当一个守卫可以被重写为其中一个参数的(无保护)案例陈述时,这不是必要的。即你可以把它写成:
foo 1 b c = [...]
foo 2 b c = [...]
foo 3 b c = [...]
[...]
这是写它的首选方式。当您想要的条件不能表示为模式时,您将使用警卫。当你需要匹配其中一个参数以外的东西时,你会使用case语句。