【问题标题】:Member function doesn't work correctly for floating point numbers成员函数不适用于浮点数
【发布时间】:2013-03-22 16:57:31
【问题描述】:

this 的答案中,以下代码的评估如下:

> let x = fromList  [0, -1, 0/0, -5, -6, -3] :: Set Float

> member 0 x
True

> let x' = insert (0/0) x

> member 0 x'
False

作者指出这是因为 EqOrd 浮点实例不遵守单子定律。 EqOrd 浮点实例如何违反单子定律,为什么会导致上述行为?

【问题讨论】:

  • 想想Set 数据类型如何存储元素(排序树)并考虑let x = 0 / 0 :: Float in compare 0 x == compare x 0 -- both are GT 的事实。当您查看错误的分支时,很难找到元素。
  • 鉴于允许 /0 会使算术完全崩溃,因此将它包含在代码中会导致错误也就不足为奇了。当你的数学老师说你不能除以零时,他们是认真的。 ;)
  • 为了记录,作者实际上声明浮点数不遵守 Eq 和 Ord 的定律,而不是说它们不遵守单子定律。这是一个类比,为什么你不应该违反法律;你引入了错误。

标签: haskell floating-point monads


【解决方案1】:

违反的不是 monad 法则,而是 Eq 相对于 Ord 的法则。

Eq 的法律要求 (==) 定义等价关系,

forall x. x == x
forall x y. x == y <=> y == x
forall x y z. x == y && y == z => x == z

Ord的约定是&lt;定义了一个总排序,

forall x. not (x < x)
forall x y. (x < y) || (x == y) || (y < x)
forall x y. not (x < y && y < x)

浮点类型违反了这些规律,因为 NaN(NaN = 非数字)与它们自身比较不相等,

0/0 /= 0/0

任何比较 &lt;, &lt;=, ... 涉及 NaN 返回 False

因此,当树中存在应该排序的 NaN 时,在搜索元素时与 NaN 进行比较可能会将递归搜索发送到错误的子树。

【讨论】:

  • 另外,我在链接答案中的Data.Set 示例源自this haskell-cafe message 中的示例。 sortminimum 的愚蠢结果可能更清楚地表明出了什么问题。
猜你喜欢
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
  • 1970-01-01
  • 2018-03-23
相关资源
最近更新 更多