As a simple exercise to get me acquainted with Haskell, after idling around on Youtube and stumbling into the American Countdown game show, I wanted to make a solver for the Numbers game.
You get 6 numbers and need to combine them with (+) (-) (*) (/)
in order to get a given result.
What I've got so far is the very brain-dead,
let operands = [75, 2, 6, 3, 8, 7] :: [Double]
let goal = 623 :: Double
let operations = [(+), (-), (*), (/)]
show (head [(a, x, b, y, c, z, d, t, e) |
a <- operands,
b <- filter (\ q -> q /= a) operands,
c <- filter (\ q -> q /= a && q /= b) operands,
d <- filter (\ q -> q /= a && q /= b && q /= c) operands,
e <- filter (\ q -> q /= a && q /= b && q /= c && q /= d) operands,
x <- operations,
y <- operations,
z <- operations,
t <- operations,
t (z (y (x a b) c) d) e == goal])
...but obviously Show doesn't know what to do with functions.
No instance for (Show (Double -> Double -> Double))
arising from a use of `show'
Possible fix:
add an instance declaration for (Show (Double -> Double -> Double))
How can I work around this? Do I need to mess with type and data constructors to make my own functions that can print or is there some easier way around it?
I would generally not advise you to implement a
Show
instance for functions. It is not the "haskelly" way of doing things, for this reason:You define a "canonical" way of showing functions. You might want them to be shown as their names now, but what if you decide to do this:
Should really the output of your program change depending on your internal implementation? That doesn't make much sense. Also, what happens to nameless functions?
Also, in another part of the program, you might want to show your functions as their types instead, etc., and then you'd have conflicting
Show
instances.Generally, only implement
Show
when you know that there should be only one way of showing that thing, and that that way works for all values that need to be shown.The simplest way of solving this problem would probably be to just store the name of the operation along with the operation. Like so:
Another option:
You cannot print the name of a function in Haskell (there may be some crazy tricks with meta programming but essentially you cannot). For your program it is probably easiest to define the list of operations as a list of pairs with a string of the name of each operator e.g.
You can get a list of just the operations by doing
map fst operations
andmap snd operations
to get their names.