patternMinor
Is there a way to simple Haskell class instance?
Viewed 0 times
simplewayinstancehaskellthereclass
Problem
I define a
and
It's very ugly and bored. I think Haskell is a Elegant language, so can I have a better style to write this?
Pixel data with different size like this.data Pixel = RGB8 Word8 Word8 Word8
| RGBA8 Word8 Word8 Word8 Word8
| RGB16 Word16 Word16 Word16
| RGBA16 Word16 Word16 Word16 Word16
| Empty
deriving (Eq)and
Num instanceinstance Num Pixel where
x + Empty = x
Empty + x = x
(RGB8 ru gu bu) + (RGB8 rv gv bv) = RGB8 (ru + rv) (gu + gv) (bu + bv)
(RGBA8 ru gu bu au) + (RGBA8 rv gv bv av) = RGBA8 (ru + rv) (gu + gv) (bu + bv) (au + av)
(RGB16 ru gu bu) + (RGB16 rv gv bv) = RGB16 (ru + rv) (gu + gv) (bu + bv)
(RGBA16 ru gu bu au) + (RGBA16 rv gv bv av) = RGBA16 (ru + rv) (gu + gv) (bu + bv) (au + av)
x - Empty = x
Empty - x = x
(RGB8 ru gu bu) - (RGB8 rv gv bv) = RGB8 (ru - rv) (gu - gv) (bu - bv)
(RGB16 ru gu bu) - (RGB16 rv gv bv) = RGB16 (ru - rv) (gu - gv) (bu - bv)
(RGBA8 ru gu bu au) - (RGBA8 rv gv bv av) = RGBA8 (ru - rv) (gu - gv) (bu - bv) (au - av)
(RGBA16 ru gu bu au) - (RGBA16 rv gv bv av) = RGBA16 (ru - rv) (gu - gv) (bu - bv) (au - av)
_ * _ = error "Not support multiply"
abs = id
signum _ = error "Not support signum"
fromInteger _ = error "Not support fromInteger"It's very ugly and bored. I think Haskell is a Elegant language, so can I have a better style to write this?
Solution
Above all, such an instance doesn't make any sense. A composite entity can't have much in common with a number, which the fact that your instance consists of just partial and undefined functions is only the evidence of.
With regards to your concern about the verbosity of the instance declaration, it was caused by you choosing an incorrect approach to type declaration.
Pixels of different bit-depths are appropriately described as different types, and not different constructors of the same type. The analogy is right before you:
Taking the said above into account I recommend you to reapproach your problem the following way:
With regards to your concern about the verbosity of the instance declaration, it was caused by you choosing an incorrect approach to type declaration.
Pixels of different bit-depths are appropriately described as different types, and not different constructors of the same type. The analogy is right before you:
Word8 and Word16 are different types, not constructors. Taking the said above into account I recommend you to reapproach your problem the following way:
-- The separate datatypes. Note the absense of `Empty` constructors, as there
-- is no such thing as empty pixel. There are black and transparent pixels,
-- which should be described as `PixelRGB8 0 0 0` or `PixelRGBA8 0 0 0 0`,
-- but not empty. And for dealing with missing pixels we have a `Maybe` type.
data PixelRGB8 = PixelRGB8 Word8 Word8 Word8
-- ...
data PixelRGBA16 = PixelRGBA16 Word16 Word16 Word16 Word16
-- We're taking an analogous approach to Num/Integral typeclasses, while
-- combining both the "to" and "from" functionality in a single typeclass.
class Pixel a where
-- whether its toPixelRGBA16 or possibly toRGBA64Pixel should depend on
-- the highest precision type you want to be dealing with
toPixelRGBA16 :: a -> PixelRGBA16
fromPixelRGBA16 :: PixelRGBA16 -> a
-- And here's addition for pixels of same type:
addPixel :: a -> a -> a
instance Pixel PixelRGB8 where
toPixelRGBA16 = error "TODO"
fromPixelRGBA16 = error "TODO"
addPixel = error "TODO"
instance Pixel PixelRGBA16 where
toPixelRGBA16 = id
fromPixelRGBA16 = id
addPixel = error "TODO"
-- Here's addition for pixels of differing types:
addArbitraryPixel :: (Pixel a, Pixel b) => a -> b -> PixelRGBA16
addArbitraryPixel a b = addPixel (toPixelRGBA16 a) (toPixelRGBA16 b)Code Snippets
-- The separate datatypes. Note the absense of `Empty` constructors, as there
-- is no such thing as empty pixel. There are black and transparent pixels,
-- which should be described as `PixelRGB8 0 0 0` or `PixelRGBA8 0 0 0 0`,
-- but not empty. And for dealing with missing pixels we have a `Maybe` type.
data PixelRGB8 = PixelRGB8 Word8 Word8 Word8
-- ...
data PixelRGBA16 = PixelRGBA16 Word16 Word16 Word16 Word16
-- We're taking an analogous approach to Num/Integral typeclasses, while
-- combining both the "to" and "from" functionality in a single typeclass.
class Pixel a where
-- whether its toPixelRGBA16 or possibly toRGBA64Pixel should depend on
-- the highest precision type you want to be dealing with
toPixelRGBA16 :: a -> PixelRGBA16
fromPixelRGBA16 :: PixelRGBA16 -> a
-- And here's addition for pixels of same type:
addPixel :: a -> a -> a
instance Pixel PixelRGB8 where
toPixelRGBA16 = error "TODO"
fromPixelRGBA16 = error "TODO"
addPixel = error "TODO"
instance Pixel PixelRGBA16 where
toPixelRGBA16 = id
fromPixelRGBA16 = id
addPixel = error "TODO"
-- Here's addition for pixels of differing types:
addArbitraryPixel :: (Pixel a, Pixel b) => a -> b -> PixelRGBA16
addArbitraryPixel a b = addPixel (toPixelRGBA16 a) (toPixelRGBA16 b)Context
StackExchange Code Review Q#23516, answer score: 4
Revisions (0)
No revisions yet.