(Re)-defining (==) for class Eq - haskell

In the following example:
data ColourName
= White
| Grey
| Gray
| Black
| Blue
-- ...
-- hundreds more of colours
-- ...
| LastColor
deriving (Read, Show, Eq)
I'd like to redefine (==) so that Grey and Gray evaluate as equal.
Obviously, one way would be to not include Eq in deriving, however, then I'd have to define
(==) :: ColourName
(==) White White = True
(==) Gray Gray = True
(==) Grey Grey = True
(==) Gray Grey = True
(==) Grey Gray = True
(==) Black Black = True
-- frickin' log of other colors, hundreds of lines of typing
(==) LastColor LastColor = True
(==) a b = False
which is nothing I plan to do.
I also can't do
instance Eq ColourName where
(==) :: ColourName -> ColourName -> Bool
(==) Gray Grey = True
(==) Grey Gray = True
(==) a b = (a == b)
because this leads to an infinite recursion, is basically underdefined.
Is there a way out?
(No, I don't want to use data Colour = Colour String or similar. I want the valid colours to be represented as an enumeration, such providing automatic validation, but want to allow spelling variation for the end users of the module!)

You can use the derived Enum instance :
data ColourName = Gray | Grey | ...
deriving (Read, Show, Enum)
instance Eq ColourName where
Gray == Grey = True
Grey == Gray = True
a == b = fromEnum a == fromEnum b
Edit: You can also use PatternSynonyms with GHC 7.8+. It works like a smart constructor, but can also be used in pattern matches.
pattern Gray = Grey

Do not do this. It won't work well with pattern matching. It will break something like
f Gray = g
f x = h
because pattern matching does not care about your Eq instance.
By break, I mean it won't have the behavior you want, since f Grey would end up calling h rather than g, even though you would expect for f x == f y for all x == y. This means the programmer has to explicitly remember to make cases for both f Gray and f Grey which is just dumb.
If you are determined to have an ugly hack to allow for alternate spellings, I suppose you can do
#define Gray Grey
with CPP enabled.

By definition the values Grey and Gray are not equal. There is nothing that suggests that they should be equal, except the extra semantics you've attached to them. I'd say this is an abuse of the Eq typeclass.
Define a function to handle these additional semantics:
sameColour :: Color -> Color -> Bool
sameColour Grey Gray = True
sameColour Gray Grey = True
sameColor a b = a == b
this can easily be extended to handle multiple colour "synonyms"

Similarly to Piezoid's answer, you could make it a bit less efficient by using the Show instance to compare them:
data ColourName = Gray | Grey | ...
deriving (Show, Read)
instance Eq ColourName where
Gray == Grey = True
Grey == Gray = True
a == b = show a == show b
Then you don't have to rely on using Enum, but you will have a bit of a performance hit from having to compare strings.

I would use a newtype here:
newtype ColourNameEquatingGrayAndGrey = CNEGAG ColourName
instance Eq ColourNameEquatingGrayAndGrey where
CNEGAG Gray == CNEGAG Grey = True
CNEGAG Grey == CNEGAG Gray = True
CNEGAG a == CNEGAG b = a == b
(Sorry about the silly type and constructor names...)
This allows you to keep deriving Eq, it makes you be very explicit about where in your code you are lumping the different spellings together, and you can still use library functions such as nub (as compared to having to switch over to nubBy sameColour (as in #cdk's answer) or something like that). You can also make your own Show instance, should you need one, and the runtime cost should be minimal.
The only downside I can think of right now is that pattern matching becomes more cumbersome, but I'm guessing that with 100s of alternatives that's not something you do at the drop of a hat!

Related

Haskell 101 | What do the Deriving Keywords mean?

Essentially practically I'm trying to implement a custom data type that is a subset of the string class (e.g. so I can do some type checking for error input). But I cannot for the life of me find anywhere that just explains what each type keyword means. According to here: Haskell Docs these are the 7 basic ones: Eq, Ord, Enum, Ix, Bounded, Read, and Show. And aside from Show which is needed for print statements and Eq which needed for boolean style comparison checks, I'm not completely certain on the other 5, and google has not been very much help. So I'm hoping y'all can shed some light and maybe point me in the correct direction.
So questions:
What are these 7 basic derives / what does adding them do?
Is there a way within ghci I can run something like derives String or derives "abc"?
Here's the code I'm working on. Essentially I've just created this Card data type which as you can see is just a string that does some more strict parameter checks. And what I'm trying to do is pass it to match which previously accepted 3 strings as an argument (now 3 Cards). But in order to use the string manipulation syntax like breaking it down into a list of characters, I believe I need to identify the appropriate derive keyword so that it behaves in this manner.
match :: Card -> Card -> Card -> Bool
match [] [] [] = True
match [a] [b] [c] = (a == b && b == c)
|| (a /= b && b /= c && a /= c)
match (a:as) (b:bs) (c:cs) = match [a] [b] [c]
&& match as bs cs
data Card = Card String
deriving (Show,Eq)
card :: String -> Card
card x | length x /= 4 = error "Card input must be 4 characters."
| (x!!0 /= 'o') && (x!!0 /= 's') && (x!!0 /= 'd') = error "char 0 (shape) must be o s or d."
| (x!!1 /= '1') && (x!!1 /= '2') && (x!!1 /= '3') = error "char 1 (number) must be 1 2 or 3."
| (x!!2 /= 'r') && (x!!2 /= 'p') && (x!!2 /= 'g') = error "char 2 (color) must be r p or g."
| (x!!3 /= 'f') && (x!!3 /= 's') && (x!!3 /= 'o') = error "char 3 (shade) must be f s or o."
| otherwise = Card x
(Updated Example #1)
data Card = Card Shape Number Color Shade deriving (Show, Eq)
data Shape = Oval | Squiggle | Diamond deriving Eq
instance Show Shape where
show Oval = "Oval"
show Squiggle = "Squiggle"
show Diamond = "Diamond"
data Number = One | Two | Three deriving Eq
instance Show Number where
show One = "One"
show Two = "Two"
show Three = "Three"
data Color = Red | Pink | Green deriving Eq
instance Show Color where
show Red = "Red"
show Pink = "Pink"
show Green = "Green"
data Shade = Full | Half | Empty deriving Eq
instance Show Shade where
show Full = "Full"
show Half = "Half"
show Empty = "Empty"
shape :: Char -> Either ShapeError Shape
shape 'o' = Right Oval
shape 's' = Right Squiggle
shape 'd' = Right Diamond
shape x = Left (NotOSD x)
number :: Char -> Either NumberError Number
number '1' = Right One
number '2' = Right Two
number '3' = Right Three
number x = Left (Not123 x)
color :: Char -> Either ColorError Color
color 'r' = Right Red
color 'p' = Right Pink
color 'g' = Right Green
color x = Left (NotRPG x)
shade :: Char -> Either ShadeError Shade
shade 'f' = Right Full
shade 's' = Right Half
shade 'o' = Right Empty
shade x = Left (NotFSO x)
card :: String -> Either SetError Card
card [shp, n, c, shd] = Card <$> shape shp <*> number n <*> color c <*> shade shd
card x = Left (NotCard x)
data CardError = NotCard String
instance Show CardError where
show (NotCard x) = "Card must be 4 characters long, not " ++ show x
data SetError = CardError | ShapeError | NumberError | ColorError | ShadeError deriving Eq
data ShapeError = NotOSD Char
instance Show ShapeError where
show (NotOSD x) = "Shape must be o, s, or d, not " ++ show x
data NumberError = Not123 Char
instance Show NumberError where
show (Not123 x) = "Number must be 1, 2, or 3, not " ++ show x
data ColorError = NotRPG Char
instance Show ColorError where
show (NotRPG x) = "Color must be r, p, or g, not " ++ show x
data ShadeError = NotFSO Char
instance Show ShadeError where
show (NotFSO x) = "Shade must be f, s, or o, not " ++ show x
Current Error
match.hs:84:34:
Couldn't match type ‘ShapeError’ with ‘SetError’
Expected type: Either SetError Shape
Actual type: Either ShapeError Shape
In the second argument of ‘(<$>)’, namely ‘shape shp’
In the first argument of ‘(<*>)’, namely ‘Card <$> shape shp’
match.hs:84:48:
Couldn't match type ‘NumberError’ with ‘SetError’
Expected type: Either SetError Number
Actual type: Either NumberError Number
In the second argument of ‘(<*>)’, namely ‘number n’
In the first argument of ‘(<*>)’, namely
‘Card <$> shape shp <*> number n’
match.hs:84:61:
Couldn't match type ‘ColorError’ with ‘SetError’
Expected type: Either SetError Color
Actual type: Either ColorError Color
In the second argument of ‘(<*>)’, namely ‘color c’
In the first argument of ‘(<*>)’, namely
‘Card <$> shape shp <*> number n <*> color c’
match.hs:84:73:
Couldn't match type ‘ShadeError’ with ‘SetError’
Expected type: Either SetError Shade
Actual type: Either ShadeError Shade
In the second argument of ‘(<*>)’, namely ‘shade shd’
In the expression:
Card <$> shape shp <*> number n <*> color c <*> shade shd
match.hs:85:16:
Couldn't match expected type ‘SetError’
with actual type ‘CardError’
In the first argument of ‘Left’, namely ‘(NotCard x)’
In the expression: Left (NotCard x)
Failed, modules loaded: none.
When writing Haskell, don't be afraid of defining lots of types and lots of small functions. Small functions are easier to understand, and can be combined in various ways to define larger functions.
Do you care about the typeclasses...
To get your immediately question out of the way, the Show instance is only used for producing a String from some value. Eq is used to allow comparing two values of the same type with ==. The other classes you can derive instances for (without GHC-specific extensions) are
Read
Ord
Enum
Bounded
Read is like the inverse of Show, but is generally not used. (The parsers I show below are easier to write than Read instances, and you won't be able to make use of derived Read instances for most of the types you'll define.) The other three may be relevant to other parts of your program, but not to any of the code in your question.
Derived Show instances basically just convert the data constructor name to a string, but as a point of good style, that string should be valid Haskell code. Derived Eq instances just check if the two data constructors are the same or not. Definitions for data constructors that take arguments are derived recursively: show (Card x) would be defined using "Card" and show x, while Card c1 == Card c2 would be define as c1 == c2.
Most of your question, though, is about pattern matching (as mentioned in the comments), which has nothing to do with type classes.
...or the types?
Let's start with your four basic concepts: shape, number, color, and shade. Define a separate type for each of them. Here's the type for Shape as an example:
data Shape = ShapeO | ShapeS | ShapeD deriving (Show, Eq)
Use descriptive names for data constructors where possible (is O really short for Oval? If so, use Oval), and keep in mind that the names must be globally unique (within a module, anyway), so you can't us O for both Shape and Shade. Sometimes the strings derived from the constructor names will be sufficient for your Show instance sometimes not. If not, rather than defining a Show instance, write your own Thing -> String function instead.
Whether you deriving the Show instance or write it manually probably depends on the data constructor names you choose and what strings you want from the values. The derived Eq instances will almost certainly be sufficient, as they do not depend on the names you use for constructor.
(As an aside, Number is tricky because you can't use 1, 2, or 3 as data constructor names. Unless you need to do math with the numbers, you might consider something like data Number = One | Two | Three instead of the overly broad data Number = Number Int.)
Now your Card type can a simple composition of your four attribute types, not just a wrapper around the raw string.
data Card = Card Shape Number Color Shade deriving (Show, Eq)
(But regarding Show, any of the attribute that have their own string-conversion function might compel you to write a Card -> String function of your own instead of relying on the Show instance.)
Parsing: strings to values
You'll want functions that parse a character into an appropriate value, not just check if it could represent an appropriate value. Sometimes this is possible ('o' for ShapeO), sometimes it is not ('x' does not represent a Shape. So your parser should account for this, but not by simply raising an exception with error. Instead, let the return type tell the caller what happened, and let them decide whether the program needs to be terminated. For example,
shape :: Char -> Either String Shape
shape 'o' = Right ShapeO
shape 's' = Right ShapeS
shape 'd' = Right ShapeD
shape x = Left $ "Shape must be o, s, or d, got ++ show x
The fact that shape returns a Right or Left value is often enough information for the caller to decide what to do next; the error message wrapped by Left is more for reporting errors to the user.
Once you have all the parsers for the individual attributes, the parser for a Card becomes almost trivial, thanks to the Applicative instance for Either String types.
card :: String -> Either String Card
card [shp, n, c, shd] = Card <$> shape shp <*> number n <*> color c <*> shade shd
card x = Left $ "Card must e 4 characters long, got " ++ show x
If any of the attributes produce a Left value, card will return the Left value of the first attribute that fails to parse. Only when the input string has exactly 4 of the correct characters will char produce a Card value wrapped with Right.
You might decide to define dedicated error types as well, rather than using arbitrary strings. For example,
data ShapeError = NotOSD Char
errorMessage :: ShapeError -> String
errorMessage (NotOSD x) = "Shape must be o, s, or d, not " ++ show x
then
shape :: String -> Either ShapeError Shape
shape 'o' = Right ShapeO
shape 's' = Right ShapeS
shape 'd' = Right ShapeD
shape x = Left (NotOSD x)
Basically, capture the information about the error in the error type, and let its Show instance produce a human-readable string with that information if needed.
Things are equal if their parts are equal
match is similarly trivial, making use of the Eq instance derived for Card, which is derived from the Eq instances for all the attribute types.
match :: Card -> Card -> Card -> Bool
match c1 c2 c3 = c1 == c2 && c2 == c3 || (c1 /= c2 && c2 /= c3 && c3 /= c1)

How to use constructors correctly when writing structures and what are the alternatives to Null?

I'm trying to write a red-black tree in haskell. In the properties of the red-black tree there is a note that all leaves that do not contain data are black.
I want to write something like this:
data EmptyNode = EmptyNode{
data = ???,
color = ???, <-- it should black (assume that it is False)
left = ???,
right = ???
}
data NodeBR a = NodeBR {
data :: a,
color :: Bool,
left :: NodeBR,
right :: NodeBR
}
data TreeBR a = EmptyNode | NodeBR a (TreeBR a) (TreeBR a)
I don't understand 2 things, what type is suitable for me to replace Null in the usual languages (undefined as I understand you can not use here) and work with constructors, how can I specify color in EmptyNode defaults to False?
One solution is to define the red-black tree (RBT for short) in a more "Haskell" way. So there are two possible ways to construct an RBT:
Leaf (EmptyNode in your code)
Node a c l r (NodeBR in your code), where a is the data, c is the color, l and r are also RBT.
data RBT a = Leaf | Node a Bool (RBT a) (RBT a)
In the line above, we have defined datatype RBT a with two constructors:
Leaf :: RBT a
Node :: a -> Bool -> RBT a -> RBT a -> RBT a
which means:
Leaf is of type RBT a
Node is a function, taking a, Bool(color), RBT a (left tree), RBT a (right tree), which returns an RBT a.
Therefore, we don't need to specify NULL in this case for Leaf, as there is no need for saying so at all (i.e., with Leaf, we want to say there is no data, no left/right subtree).
To treat Leaf as black, we could ## Heading ##define a function on RBT a using pattern matching:
color :: RBT a -> Bool
color Leaf = False
color (Node _ c _ _) = c
The record syntax which you have mentioned in your code is just syntactic sugar for generating such color function. But in this case, using record syntax cannot generate the correct code for the Leaf case, as they are not identical in the declaration.
Thus, when you have to check if an RBT a is Leaf or not, you can just use pattern matching instead of "if-with-null" in other languages.
Update:
As mentioned by amalloy in the comments, we could define the color as a separate datatype for better readability:
data Color = Red | Black
data RBT a = Leaf | Node a Color (RBT a) (RBT a)
color :: RBT a -> Color
color Leaf = Black
color (Node _ c _ _) = c
Note that Bool and Color are isomorphic.

Implement Enum Instance behavior on custom data type in Haskell

I've got a custom data type in Haskell to represent a traffic light
data TrafficLight = Red | Yellow | Green
I'm attempting to implement the features of the Enum typeclass using an instance block like so:
instance Enum TrafficLight where
succ Green = Yellow
succ Yellow = Red
succ Red = Green
pred Green = Red
pred Yellow = Green
pred Red = Yellow
pred and succ work as expected, however I'd also like to implement the range function, such that I'd be able to call
ghci> [Green .. Red]
and have it return
[Green,Yellow,Red]
I understand that this functionality seems to come from the enumFrom function in the Enum typeclass, but I'm not completely sure how to implement it the say way I implemented pred and succ.
The description for enumFrom at haskell.org gives the following possible definition enumFrom n = n : enumFrom (succ n). It should work in your case.

Get data of type without pattern match on all data contructors

Is there a way to make abstraction of the data type and just use the values?
data Color a = Blue a | Green a | Red a | Yellow a | Magenta a deriving (Show)
Something like :
calcColor :: Color a -> Color a -> Maybe a
calcColor (_ x) (_ y) = Just $ x + y
It doesn't have to be necessarily in the function declaration.
One option I was thinking was to have something like fromJust but even that feels a little redundant.
fromColor :: Color a -> a
fromColor (Blue t) = t
fromColor (Red t) = t
fromColor (Green t) = t
fromColor (Yellow t) = t
Edit - added context and more clarifications
From the way I managed to question it, the title might look like a duplicate question.
I'm not that sure, but that is for the community to decide.
I pretty new to Haskell so maybe my question looks stupid but still I think it's a valid case because I actually have this situation.
#FyodorSoikin, #leftaroundabout Your answers helps me, but partially. I'll try make explain better what exactly I would like to achive.
I want to think at the Color type like a category (let's say G), the colors beeing elements of the G,
and I also have phones that come in different colors. The phones category (let's say H).
Now I have I try to come with a way to make use of the morphisms (functions) of the G category using a functor in the H category or the other way around.
For example : determine the future stocks of a color type based on the sales of phones.
I want to understand to what extend I can create a types like Color to have the advantages of a type ustead of using a string value.
You could do a hack like
{-# LANGUAGE DeriveFoldable #-}
import Data.Foldable (Foldable, toList)
data Color a = Blue a | Green a | Red a | Yellow a | Magenta a
deriving (Show, Foldable)
fromColor :: Color a -> a
fromColor c = case toList c of
[ca] -> ca
_ -> error "Impossible, `Color` has only one field."
But I agree with Fyodor Soikin's comment: why have the a field in each constructor in the first place? Just factor it out
data Hue = Blue | Green | Red | Yellow | Magenta
data Color a = Color { hue :: Hue, value :: a }
Based on your edit, it looks like you are looking for a basic vocabulary for dealing with Color. That can be provided both by class instances and by special-purpose functions.
A Functor instance, for example, allows you to change the a value in a Color a independently of the color itself:
data Hue = Blue | Green | Red | Yellow | Magenta
deriving (Eq, Show)
data Color a = Color { hue :: Hue, value :: a }
deriving (Eq, Show)
instance Functor Color where
fmap f (Color h a) = Color h (f a)
GHCi> test1 = Color Red 27
GHCi> fmap (2*) test1
Color {hue = Red, value = 54}
Two brief notes:
The things I'm suggesting here can be done equally as well with your four-constructor Color type or with leftaroundabout's single-constructor one. The latter, though, should be easier to work with in most situations, so I'll stick with it.
The DeriveFunctor extension means you almost never have to write a Functor instance explicitly: turn it on by adding {-# LANGUAGE DeriveFunctor #-} to the top of your file and then just write:
data Color a = Color { hue :: Hue, value :: a }
deriving (Eq, Show, Functor)
Another thing you might want to do is having a Hue -> Colour a -> Maybe a function, which would give you a way to use operations on Maybe to filter the a values by their attached hue:
colorToMaybe :: Hue -> Color a -> Maybe a
colorToMaybe chosenHue col
| hue col == chosenHue = Just (value col)
| otherwise = Nothing
GHCi> test1 = Color Red 27
GHCi> test2 = Color Red 14
GHCi> test3 = Color Blue 33
GHCi> import Data.Maybe
GHCi> mapMaybe (colorToMaybe Red) [test1, test2, test3]
[27,14]
GHCi> import Control.Applicative
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test2)
Just 41
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test3)
Nothing
These are just rather arbitrary suggestions. The specifics of what you'll want to define will depend on your use cases.

Haskell deriving additional instances for imported datatypes

I'm relatively new to Haskell. I write a clone of the card game uno and i want pretty coloured output of a card. I do
import System.Console.ANSI
which provides
data Color = Black
| Red
| Green
| Yellow
| Blue
| Magenta
| Cyan
| White
deriving (Bounded, Enum, Show)
now i want to add deriving (Ord, Eq) as well, i could write this in the source file of the imported package, but there should be an easier way to do this.
i don't have a clue what keywords to google for or look for in a book.
No need to edit the library. In your source file, state:
instance Eq Color where
x == y = fromEnum x == fromEnum y
instance Ord Color where
compare x y = compare (fromEnum x) (fromEnum y)
Explanation: fromEnum is a function on Enum that returns an int (Black -> 0, Red -> 1, etc.). Integers are obviously equality-comparable and ordered.
Edit: #rampion's version, in the comments, is obviously prettier:
instance Eq Color where
(==) = (==) `on` fromEnum
instance Ord Color where
compare = compare `on` fromEnum

Resources