【问题标题】:Eq instance has some strange comparisonsEq 实例有一些奇怪的比较
【发布时间】:2011-04-23 19:26:12
【问题描述】:

我制作了一个图像处理模块,将Pixel 类型定义为ColorLocationPixelColorLocation 派生 Eq,因为我可能想比较多个图像之间的像素。

Eq 适合我比较像素以查看它们是否完全相同的需求,这正是我想要的。实例化 Eq 的一个奇怪副作用是,将具有相同 Location 的 2 个不同像素与 <=>= 进行比较会得到 True,但 False 对应于 ==<>.

data Color = Color { red   :: Int
                   , green :: Int
                   , blue  :: Int
                   , alpha :: Int
                   } deriving ( Show, Eq )

data Location = Location { x :: Int
                         , y :: Int
                         } deriving ( Show, Eq, Ord )

data Pixel = Pixel { color    :: Color
                   , location :: Location
                   } deriving ( Show, Eq )

instance Ord Pixel where
         compare (Pixel _ a) (Pixel _ b) = compare a b

然后在 ghci 中进行一些测试。

>let a = Pixel (Color 0 0 0 255) (Location 0 0)
>let b = Pixel (Color 0 0 1 255) (Location 0 0)
>let c = Pixel (Color 0 0 0 255) (Location 0 0)
>let d = Pixel (Color 0 0 0 255) (Location 0 1)
>a == b
False
>a /= b
True
>a < b
False
>a > b
False
>a <= b
True
>a >= b
True
>a == c
True
>a /= c
False
>a > c
False
>a < c
False
>a >= c
True
>a <= c
True
>a == d
False
>a /= d
True
>a > d
False
>a < d
True
a >= d
False
a <= d
True

似乎我为Pixel 定义的Ord 影响了这些比较,这是可以理解的。 d 表明Location 影响比较。我感到困惑的部分是 a 如何既是 &gt;= 又是 &lt;= b 而不是 ==&lt;&gt;

编辑:如果有人想使用此代码中的任何一个,我将包含此解决问题的 sn-p。请务必从 Pixel 定义中删除 Eq

instance Eq Pixel where
            (Pixel _ a) == (Pixel _ b) = a == b
            (Pixel _ a) /= (Pixel _ b) = a /= b

这仅允许比较 Location。享受! :)

【问题讨论】:

  • 值得注意的是,位置的 Ord 实例可以说在 2D 中没有合理的几何解释(默认的字典顺序偏向于水平分量)。也就是说,如果您想按位置索引 Data.Map,则需要一个 Ord 实例。同样,可以说颜色对于某些颜色模型只有合理的排序——例如。您可以根据其黑暗/明亮度订购 HSV 颜色。

标签: haskell comparison ghc typeclass deriving


【解决方案1】:

我感到困惑的部分是a 如何既大于或等于又小于或等于b 而不是等于、小于或大于。

通过为Pixel 引入您的自定义Ord 实例,同时仍在派生 Eq,你有一个有趣的结果:

  • 像素将根据其颜色和位置具有完全的结构相等性
  • 但是,为了给他们下订单,您要求忽略颜色。

这会让事情变得奇怪,因为有些事情会比较 EQ(仅基于相同的位置),同时,如果您 测试与(==) 是否相等,值将不相等,因为颜色是 也包括在内。

基本上你已经让EqOrd 实例变得不健全。

要么派生EqOrd,获得完全的结构平等和 订购,或手动编写一个丢弃颜色信息的Eq 实例, 就像您现有的 Ord 实例一样。

【讨论】:

  • 我想接受你的两个答案,但是由于这个有关于如何解决它的信息,我会接受这个。
【解决方案2】:

因为您的 Ord 实例会忽略颜色,但派生的 Eq 实例不会。 a == b 为假,因为 == 是 Eq 类型类的方法,派生方法将考虑颜色。
a &lt;= b 为真,因为 &lt;= 是 Ord 类型类的一部分,并且您的比较实现忽略颜色这意味着 compare a b == EQ 如果 a 和 b 具有相同的位置,而不管它们的颜色如何。

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 2014-08-14
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    相关资源
    最近更新 更多