3

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

Eq适合我比较像素以查看它们是否完全相同的需要,这正是我想要的。实例化的一个奇怪的副作用Eq是,将 2 个不同的像素与相同Location的像素进行比较<=>=结果为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

似乎我Ord对 a 的定义Pixel影响了这些比较,这是可以理解的。d表明Location影响比较。我感到困惑的部分是a是既>=<= b而不是==, <, or >

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

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

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

4

2 回答 2

9

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

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

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

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

从本质上讲,您已经使EqOrd实例变得不健全。

要么同时派生Eqand Ord,获得完整的结构相等性和排序,要么手动编写一个Eq丢弃颜色信息的实例,就像您现有的Ord实例一样。

于 2011-04-23T19:39:22.050 回答
3

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

于 2011-04-23T19:34:15.613 回答