Haskell deriving additional instances for imported datatypes - haskell

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

Related

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: is there a way of 'mapping' over an algebraic data type?

Suppose that I have some simple algebraic data (essentially enums) and another type which has these enums as fields.
data Color = Red | Green | Blue deriving (Eq, Show, Enum, Ord)
data Width = Thin | Normal | Fat deriving (Eq, Show, Enum, Ord)
data Height = Short | Medium | Tall deriving (Eq, Show, Enum, Ord)
data Object = Object { color :: Colour
, width :: Width
, height :: Height } deriving (Show)
Given a list of objects, I want to test that the attributes are all distinct. For this I have following functions (using sort from Data.List)
allDifferent = comparePairwise . sort
where comparePairwise xs = and $ zipWith (/=) xs (drop 1 xs)
uniqueAttributes :: [Object] -> Bool
uniqueAttributes objects = all [ allDifferent $ map color objects
, allDifferent $ map width objects
, allDifferent $ map height objects ]
This works, but is rather dissatisfying because I had to type each field (color, width, height) manually. In my actual code, there are more fields! Is there a way of 'mapping' the function
\field -> allDifferent $ map field objects
over the fields of an algebraic datatype like Object? I want to treat Object as a list of its fields (something that would be easy in e.g. javascript), but these fields have different types...
Here is a solution using generics-sop:
pointwiseAllDifferent
:: (Generic a, Code a ~ '[ xs ], All Ord xs) => [a] -> Bool
pointwiseAllDifferent =
and
. hcollapse
. hcmap (Proxy :: Proxy Ord) (K . allDifferent)
. hunzip
. map (unZ . unSOP . from)
hunzip :: SListI xs => [NP I xs] -> NP [] xs
hunzip = foldr (hzipWith ((:) . unI)) (hpure [])
This assumes that the type Object you want to compare is a record type and requires that you make this type an instance of the class Generic, which can be done using Template Haskell:
deriveGeneric ''Object
Let's try to see what's going on here by looking at a concrete example:
objects = [Object Red Thin Short, Object Green Fat Short]
The line map (unZ . unSOP . from) converts each Object into a heterogeneous list (called an n-ary product in the library):
GHCi> map (unZ . unSOP . from) objects
[I Red :* (I Thin :* (I Short :* Nil)),I Green :* (I Fat :* (I Short :* Nil))]
The hunzip then turns this list of products into a product where each element is a list:
GHCi> hunzip it
[Red,Green] :* ([Thin,Fat] :* ([Short,Short] :* Nil))
Now, we apply allDifferent to each list in the product:
GHCi> hcmap (Proxy :: Proxy Ord) (K . allDifferent) it
K True :* (K True :* (K False :* Nil))
The product is now in fact homogeneous, as every position contains a Bool, so hcollapse turns it into a normal homogeneous list again:
GHCi> hcollapse it
[True,True,False]
The last step just applies and to it:
GHCi> and it
False
For this very specific situation (checking a set of attributes that are simple sum types with 0-arity constructors), you can use the following construction using Data.Data generics:
{-# LANGUAGE DeriveDataTypeable #-}
module Signature where
import Data.List (sort, transpose)
import Data.Data
data Color = Red | Green | Blue deriving (Eq, Show, Enum, Ord, Data)
data Width = Thin | Normal | Fat deriving (Eq, Show, Enum, Ord, Data)
data Height = Short | Medium | Tall deriving (Eq, Show, Enum, Ord, Data)
data Object = Object { color :: Color
, width :: Width
, height :: Height } deriving (Show, Data)
-- |Signature of attribute constructors used in object
signature :: Object -> [String]
signature = gmapQ (show . toConstr)
uniqueAttributes :: [Object] -> Bool
uniqueAttributes = all allDifferent . transpose . map signature
allDifferent :: (Ord a) => [a] -> Bool
allDifferent = comparePairwise . sort
where comparePairwise xs = and $ zipWith (/=) xs (drop 1 xs)
The key here is the function signature which takes an object and generically across its immediate children calculates the constructor name of each child. So:
*Signature> signature (Object Red Fat Medium)
["Red","Fat","Medium"]
*Signature>
If there are any fields other than these simple sum types, (like say an attribute of type data Weight = Weight Int or if you added a name :: String field to Object), then this will suddenly fail.
(Edited to add:) Note that you can use constrIndex . toConstr in place of show . toConstr to use an Int-valued constructor index (basically, the index starting with 1 of the constructor within the data definition), if this feels less indirect. If the Constr returned by toConstr had an Ord instance, there would be no indirection at all, but unfortunately...

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

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!

How to write customised show function in Haskell

I am defining a Octave type:
data Octave = 1 | 2 | 3
deriving (Show, Read, Ord, Enum)
Since '1' is not valid for data constructor identifiers, I have to do it like so:
data Octave = O1 | O2 | O3
deriving (Show, Eq, Read, Ord, Enum)
Now, if I show Octave O1 it shows "O1" which is not exactly what I want. I want the result to be "1". I know we can customise our Show behaviour like this:
instance Show Blabla where
show (Blabla ints chars list num) =
"integers = " ++ show ints ++ "\n"
But the problem is that I am using enumeration type which means it doesn't have a value except its identifier name 'O1'. How can I access that in Haskell?
Another question: How can I read it back?
read "O1" :: Octave works, but I want read "1" :: Octave
instance Read Octave where
read "1" = O1
read "2" = O2
read "3" = O3
This doesn't work: "read is not a (visible) method of class Read".
Taking advantage of Octave's Enum instance and using the Show and Read instances for Int we can implement showing and reading like this:
data Octave = O1 | O2 | O3 deriving (Eq, Ord, Enum)
instance Show Octave where
show o = show (fromEnum o + 1)
instance Read Octave where
readsPrec prec = map (\(n,s) -> (toEnum (n - 1), s)) . readsPrec prec
I.e. fromEnum and toEnum convert between octaves and ints so that O1 <-> 0 and O2 <-> 1, so we have to adjust by one in both reading and writing.
Seems like all you need is this, right?
instance Show Octave where
show O1 = "1"
show O2 = "2"
show O3 = "3"
Define show with three clauses, and let the pattern matcher figure it out.
Here's a different approach:
data Octave_ = O1 | O2 | O3 deriving (Show, Eq, Read, Ord, Enum)
newtype Octave = O { unO :: Octave_ } deriving (Eq, Ord, Enum)
instance Show Octave where
show = tail . show . unO
Depending on what you are doing this could be good or bad.
You can always use existing instances for Int, like so:
data Octave = O1 | O2 | O3 deriving (Enum,Bounded)
instance Show Octave where
show = show . (+1) . fromEnum
instance Read Octave where
readsPrec pr = map (\ (int,str) -> ((toEnum (int-1)),str) . readsPrec pr
This correctly renders O1..O3 as 1..3 and reads them back. The only pitfall is when trying to read a different integer, like 4:
*** Exception: toEnum{Octave}: tag (3) is outside of enumerations'range (0,2)
This could be fixed by writing more code and checking for valid values in readsPred.
It looks like you want to access the identifier name. you could use something like template haskell to do it but this is a terrible idea.
Actually, the fist bad idea is probably to rely on show. Show class is traditionally use to "serialize" data, while Read class will de-serialize them. If you want to pretty print the output, you'd better write your own Octave -> String function. To do so, you could rely on the result of show (and truncate the result). However, the most efficient solution might be to encode it directly, as proposed by amalloy.

Haskell Enumerations starting from 1

Consider the following method to create a start-at-1 enumeration in Haskell:
data Level = Lower | Middle | Upper
deriving (Show, Eq, Ord)
instance Enum Level where
toEnum 1 = Lower
toEnum 2 = Middle
toEnum 3 = Upper
fromEnum Lower = 1
fromEnum Middle = 2
fromEnum Upper = 3
instance Bounded Level where
minBound = Lower
maxBound = Upper
I'd rather not do the following:
data Level = DontUseThis | Lower | Middle | Upper
deriving (Show, Eq, Ord)
If not, is there a more straightforward way to do this?
First of all, you don't need to define the Bounded instance yourself. If you add Bounded to the list of derived typeclasses you should get identical behavior.
Secondly, the most straightforward way I can think of to accomplish this is to simply derive Enum and then define your own translation functions. So something like this:
data Level = Lower | Middle | Upper
deriving (Show, Eq, Ord, Bounded, Enum)
toEnum' x = toEnum (x - 1)
fromEnum' x = (fromEnum x) + 1
You can write it a little bit more concise (well, if you have more than 3 constructors) using:
import Data.List (elemIndex)
import Data.Maybet (fromJust)
values = [Lower, Middle, Upper]
instance Enum Level where
toEnum n = values !! (n-1)
fromEnum k = 1 + fromJust $ elemIndex k values

Resources