1
votes

I created a type in Haskell which represents a pixel, like so:

data Pixel = Pixel Float Float Int deriving (Eq, Show)

Here, the first float corresponds to the pixel's location on the x axis, the second float represents the location in the y axis (so basically I have 2 coordinates for it on the "screen") and the Int it's its grey value.

I wanted to create and instance of Eq for Pixel in which a pixel is equal to each other if their grey value is the same, regardless of its position.

So far I've done this:

instance Eq Pixel where

but now I don't know how to check if they're the same, I mean, how do I say I have 2 diferent Pixels here and I want to compare their Int? I can't do something like

grey1 == grey2 = True

'cause I don't know where grey1 and grey2 came from.

How can I do it?

Also when doing a instance for Show, how do I refer to the Floats and the Int?

3
You almost certainly do not want to define an Eq that only compares on one field, and it's very likely to lead to headaches later if you do anything even slightly complex with it. - Tom Ellis
BTW thing you defined looks more like "point" than "pixel". Pixel doesn't keep its position by itself. - user3974391

3 Answers

4
votes

Something like this?

data Pixel = Pixel Float Float Int

instance Eq Pixel where 
    Pixel _ _ g1 == Pixel _ _ g2 = g1 == g2

instance Show Pixel where
    show ( Pixel  x y g ) = "Pixel " ++ show g ++ " at ("  ++ show x ++ "," ++ show y ++ ")"
4
votes

Use record syntax instead!

data Pixel = Pixel {   xPos :: Float
                     , yPos :: Float
                     , value :: Int  
                     }

xPos, yPos and value have types Pixel -> Float and Pixel -> Int which will make some operations easier than pattern matching.

However, to make it an instance of appropriate classes it's sufficient (examples):

instance Show Pixel where
    show (Pixel x y g) = "[" ++ show x ++ ", " ++ show y ++ "(" ++ show g ++ ")]"

instance Eq Pixel where
    (Pixel _ _ valA) == (Pixel _ _ valB) = valA == valB

The same with record syntax actually used:

instance Show Pixel where
    show pixel = "[" ++ show (xPos pixel) ++ ", " ++ show (yPos pixel) ++ "(" ++ show (value pixel) ++ ")]"

instance Eq Pixel where
    a == b = (value a) == (value b)

You might need to modify the examples; they are just for illustrative purposes.

3
votes

What you'd like to do is pattern match on the constructor of Pixel. This is how you write functions which "pull apart" a type. Pattern matching happens using the case statement

case pixel of
  Pixel x y grey -> ...

Which, as syntax sugar, is also available directly in definitions

getX :: Pixel -> Double
getX (Pixel x y grey) = x

-- same as

getX :: Pixel -> Double
getX px = case px of
  Pixel x y grey -> x

So we do this twice to create an equality function

instance Eq Pixel where
  Pixel x1 y1 grey1 == Pixel x2 y2 grey2 = grey1 == grey2