Haskell 哪一种是首选的写作方法;卫兵;?

Haskell 哪一种是首选的写作方法;卫兵;?,haskell,Haskell,我已经创建了一个可以使用(据我所知)大小写表达式或保护的函数 foo a b c = case a of 1 -> [...] 2 -> [...] 3 -> [...] [...] otherwise -> error "..." 或 所以,问题是:这两个(外壳或防护装置)中哪一个是“更好”的

我已经创建了一个可以使用(据我所知)大小写表达式或保护的函数

foo a b c = case a of 1 -> [...]
                      2 -> [...]
                      3 -> [...] 
                      [...]
                      otherwise -> error "..."


所以,问题是:这两个(外壳或防护装置)中哪一个是“更好”的编码?两者基本相同吗?

当一个保护可以在其中一个参数上重写为(无保护的)case语句时,实际上没有必要这样做。也就是说,你可以这样写:

foo 1 b c = [...]
foo 2 b c = [...]
foo 3 b c = [...]
[...]

哪一种是写它的首选方式。当您想要的条件无法表示为模式时,您会使用防护。当您需要匹配某个参数以外的其他参数时,可以使用case语句。

第一个被认为是更好的样式,原因有二

首先:许多人会说它看起来更好,因为您不必键入所有的
=
。当然,这是一个非常主观的原因。此外,您通常甚至不会引入新的case语句,只需匹配函数参数列表中的参数,如下所示:

foo 1 b c = ... -- etc
...
foo _ b c = ... -- for the "otherwise" part
这使得代码更加紧凑和可读,这是许多人喜欢的

第二,实际上存在语义差异。假设您有这样一种数据类型:

data Cake = Apple | Cheese | Cream
| a == Apple = "fruit"
| otherwise  = "not fruit"
如果使用第一种方法,则与表达式的
case..中的构造函数匹配:

case a of
  Apple -> "fruit"
  _     -> "not fruit"
但是,如果您尝试执行某种类型的保护表达式,例如:

data Cake = Apple | Cheese | Cream
| a == Apple = "fruit"
| otherwise  = "not fruit"

。。。它实际上不会工作,因为
Cake
类型没有
Eq
实例,所以不能使用
==
来比较两个值。引入
Eq
实例(在数据定义之后使用
派生(Eq)
)并不总是需要的,因此在这种情况下不必这样做可能很重要。

在第一个示例中,您不应该使用
否则就不应该这样使用
。它所做的是引入一个名为
的新变量,否则=a
,这可能会导致微妙的错误。您应该改为执行
\uuu->error“…”
。@dflemstr感谢您提供的信息和解释。作为一般的跨语言技巧,我更喜欢在下一行编写代码子块,并且始终使用相同的缩进级别。如果第一行的长度发生了变化(可能是因为foo被重命名或其他原因),这可以避免您必须重新删除其余的行。实际上,我有一些基本情况(我相信我可以称它们为基本情况–我是编码的初学者),比如“如果a==1&&b>c,那么(…)”。所以,如果应用您的建议,它可能会使我的代码可读性稍差,我想(?)。实际上(第2部分)。。。我想我能应用你的建议。。。看起来不错^^如果它们在语义上不同,你怎么能说一个比另一个更好?@AdamWagner因为在许多情况下,你可以选择使用结果完全相同的一个(通过“比较生成的机器代码”)。请注意,如果在函数定义中使用case语句而不是直接模式匹配,不同的案例可以共享相同的
where
子句,就像警卫一样。