I would like to put the 2 functions (color and check) into the most general form
Eq a => ....
But I don’t know how to do that.
This is a very simple graph: each node has 2 neighbours, and any adjacent nodes must have different colors
color :: [(Int, Int)] -> [(Int, Int)] -> Bool
color x [] = True
color a ((x,y):rest) =
if check a x == check a y
then False
else color a rest
check :: [(Int, Int)] -> Int -> Int
check [] x = 999
check ((x,y):rest) p =
if x == p
then y
else check rest p
At the end, colors gives you True or False
Main> colors [('a',"purple"),('b',"green"),('c',"blue")] [('a','b'),('b','c'),('c','a')]
True
Main> colors [('a',"purple"),('b',"green"),('c',"purple")] [('a','b'),('b','c'),('c','a')]
False
Main> colors [('1',"purple"),('2',"green"),('3',"blue")] [('1','2'),('2','3'),('3','1')]
True
Main> colors [('1',"4"),('2',"5"),('3',"6")] [('1','2'),('2','3'),('3','1')]
True
Main> colors [('1',"4"),('2',"4"),('3',"5")] [('1','2'),('2','3'),('3','1')]
False
Any help is welcome (+ if you can fix x = 999 into False).
For starters, the reason you can’t generalize the
Intto anEq ais because of the 999 hard-coded incheck. If you just leave some random value in there, you must know its type, so you cannot generalize the function beyond that (well, in this particular case, you can generalize toEq a, Num a, but not more).So, the answer is to not use some arbitrary value, but instead wrap the return of
checkinto a type that has a “failure” case, namelyMaybe.Renaming the variables to follow Haskell conventions, and giving the functions a bit more elucidating names, we get:
The idea here is that
findNeighbourreturnsNothingif it can’t find anything, orJust 23if it finds 23 (or whatever it finds).As it happens,
findNeighbouris already defined: it’s calledlookup. So, you could rewrite your code as:Now, we note that you are basically checking a predicate against all items in a list. There’s a function for this:
all. So, we can shorten the code to: