【问题标题】:Understanding Haskell's Bool Deriving an Ord理解 Haskell 的 Bool 推导 Ord
【发布时间】:2014-05-27 03:29:11
【问题描述】:

Learn You a Haskell 表示Bool 类型:

data Bool = False | True deriving (Ord)

我不明白比较Bool的原因。

> False `compare` True
LT
> True `compare` False
GT

如果Bool 不是从Ord 派生的,会丢失什么?

【问题讨论】:

  • 好吧,你不能有 Map 的布尔值。没有Ord 实例有什么好处?另外,请注意,如果没有预先存在的 instance Ord Bool,您不能轻易地为包含 Bool 的任何类型派生 Ord
  • 指标函数怎么样?来自枚举。 (elem [1,2,3]) 如果应用于集合的元素,则为 1,否则为 0?
  • 我觉得应该叫“派生Ord实例”而不是“派生自Ord”。
  • 感谢@chaosmasttter。我刚刚更新了您的更正。

标签: haskell boolean


【解决方案1】:

Bool 形成一个bounded lattice*,其中False底部True顶部。这个有界格定义了一个(总)排序,其中False 确实严格小于True。 (它们也是这个格子的唯一元素。)

布尔运算andor 在此格中也可以分别视为meetjoin。 Meet 找到最大的下界,而 join 找到最小的上界。这意味着a && False = False 与说bottom 的下限和其他任何东西都是bottom 相同,a || True = True 与说top 的上限和任何东西都是top 相同。所以使用布尔值的排序属性的 meet 和 join 等价于你所熟悉的布尔运算。

您可以使用 minmax 在 Haskell 中显示此内容:

False `min` True = False -- this is the greatest lower bound
False  &&   True = False -- so is this

False `max` True = True  -- this is the least upper bound
False  ||   True = True  -- so is this

这表明您可以从派生的Ord 实例中定义&&|| 只是

(&&) = min
(||) = max

请注意,在存在a different kind of bottom 的情况下,这些定义不等效,因为(&&)(||) 是短路的(当第一个参数分别为FalseTrue 时,第二个参数是非严格的) 而minmax 不是。

另外,一个小的修正:deriving 子句没有说Bool“派生自”Ord。它指示 GHC 派生一个类型类 Ord 的实例for 类型 Bool

* 更具体地说,一个互补分布格。更具体地说,boolean algebra

【讨论】:

  • (&&) = min; (||) = max 与典型定义之间存在差异:它们具有不同的严格属性,因此,例如,它们对底部的行为不同(undefined 等意义上的“底部”) . (&&)(||) 短路。
  • 好点。如果您认为有帮助,我可以添加通常的“从上到下”的警告。
  • 你能告诉我meetjoin的意义吗?我把你关于它们的段落读了两遍,但我不明白。具体来说,Bool 的least upper bound & greatest lower bound 是什么意思?
  • @DavidYoung:为什么它们应该有所不同? minmax 是根据 compare 或比较运算符定义的,没有理由为什么它们的严格性必须不同于 (&&)(||)
  • @newacct (&&)(||) 是根据短路模式匹配定义的。要让compare 给出结果(至少在Bool 上),它必须评估两个参数,因为它们有可能相等。考虑True || undefinedTrue `max` undefined之间的区别
【解决方案2】:

当您需要比较内部某处包含Bool 的值时,BoolOrd 实例变得更加重要。例如,如果没有它,我们将无法编写如下表达式:

[False,True] `compare` [False,True,False]

(3, False) < (3, True)

data Person = Person { name :: String, member :: Bool } deriving (Eq, Ord)

等等

【讨论】:

    【解决方案3】:

    这是因为 Haskell 的设计者犯了一个错误!我从未见过提到布尔排序的数学教科书。只是因为他们可以,这并不意味着应该。我们中的一些人使用 Haskell 正是因为它在许多情况下不允许/保护我们免受混淆/荒谬的事情的影响,但不是这个。

    instance Ord Bool 导致 a =&gt; b 的含义与您期望 a &lt;= b 的含义相同!

    支持instance Ord Bool 的早期论点可以使更多类型隐含地进行比较。继续这一论点,有些人可能希望使每种类型都具有隐含的可比性,甚至具有弱动态类型并完全省略类型类。但我们希望强类型完全禁止明显不正确的内容,而instance Ord Bool 违背了这一目的。

    关于 Bool 是有界格的说法。与 boolean:={True,False} 不同,我们在 Haskell 中拥有的是 Bool:={True,False,bottom} 不再是有界格,因为 True 和 False 都不是底部存在的单位元素。这与那些讨论 && vs min 等的 cmets 有关。

    【讨论】:

    • 我不同意你的论点。许多 monad 实例在存在底部时也是不正确的,但我们仍然使用它们。
    • 在 Haskell 中,对事物进行“自上而下”的推理是很常见的,对此我提出了警告。我们可以这样做是因为它在Fast and Loose Reasoning is Morally Correct (PDF) 中探讨的意义上是“道德上正确的”:如果两个术语在整体语言中具有等效语义,那么它们在部分语言中具有 相关 语义,所以我们仍然可以有效地推理 Haskell 中的语义,尽管它是偏颇的。
    猜你喜欢
    • 1970-01-01
    • 2022-11-21
    • 2017-01-04
    • 2018-10-11
    • 1970-01-01
    • 2016-07-12
    • 2021-08-06
    • 2020-05-01
    • 1970-01-01
    相关资源
    最近更新 更多