为什么在 Haskell 中另外定义为 True?

hey*_*you 4 haskell

我刚刚发现 Haskell 中的守卫方程,这是一个例子:

abs n | n >= 0 = n
      | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

它基本上表示函数abs返回nif n >= 0,否则返回-n

书中说标准前奏的定义是这样的:otherwise = True,为什么呢?

Pet*_*all 8

存在的原因以及它如此定义的原因纯粹是出于风格目的otherwise您给出的示例也同样有效,可以这样写:

abs n | n >= 0 = n
      | True = -n
Run Code Online (Sandbox Code Playgroud)

otherwise只是读起来更好看。特别是它读起来就像一个数学定义。


Ben*_*Ben 5

这是一个可爱的技巧,因此您可以编写像您引用的那样的定义:

abs n | n >= 0 = n
      | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

这看起来相当简单(如果您熟悉数学符号约定),就像它说的那样“ abs n,如果 n 大于或等于零,则等于n,否则等于-n”。

But the simple guard syntax is always the guard symbol |, followed by a condition, followed by the = symbol, followed by the resulting expression. There isn't actually any way in that syntax to express an "else"/"otherwise" case that applies with no condition of its own, if all of the other conditions failed.

Somebody early on noticed that the guard syntax provides a way of getting the effect of an "otherwise" case. Since the guard conditions are checked in order, top-down, you can simply give the last one a condition of True. That will always match, but since you wrote it last it will only be checked if all the other conditions failed. That would give you:

abs n | n >= 0 = n
      | True = -n
Run Code Online (Sandbox Code Playgroud)

But the simple appearance of True doesn't immediately communicate the idea of "else" or "otherwise". So someone had the bright idea of putting a standard definition in the prelude:

otherwise :: Bool
otherwise = True
Run Code Online (Sandbox Code Playgroud)

Now we can write:

abs n | n >= 0 = n
      | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

And we've visually got the idea of an "else" case in our guards, without changing the compiler to implement more complex syntax! Brilliant!

说实话,我不确定今天是否定义了我们会这样做的语言。现在有点奇怪,这otherwise是一个半保留的名字。在您自己的代码中,您可能在满足某些外部条件时进行绑定,并且在不满足任何条件时需要捕获所有绑定。如果你不小心调用了它,otherwise你可能会收到有关阴影的警告,或者如果你碰巧尝试在绑定| otherwise = ...范围内使用该习惯用法,你可能会收到奇怪的错误otherwise(或者最糟糕的是,如果你的otherwise类型实际上是,Bool并且是False,你可能会抓狂)试图找出为什么你的| otherwise守卫没有开火)。我们甚至还没有真正获得在不修改编译器的情况下获得这种漂亮的额外语法的能力,因为编译器必须知道otherwise在其详尽性检查中进行一些特殊处理!(或者也许不是,它依赖于普通的内联来识别包罗万象的True条件......我的其余观点仍然成立)

TLDR:您可以将| otherwise其视为“无条件保护”的特殊语法。该概念实际上是通过简单地成为的 Prelude 定义来实现的,但您通常应该忽略它(它不适合您在任何其他上下文中的布尔表达式中实际使用)。otherwiseTrue otherwise

  • 同意,这是一个有点愚蠢的解决方案。我想知道如果允许完全省略一个条件是否会导致任何解析问题。这是足够合理的,因为它已经被允许写入多个,以逗号分隔,并用 and 组合在一起——所以空条件自然对应于常量 `True`。而且读起来仍然非常清晰。 (2认同)