Question

I'm trying to solve the 8 queens problem in Haskell without the use of any advanced functions, only with basic knowledge. I have come this far only but I'm getting an error that I can't understand. The code:

queens = [[x1,x2,x3,x4,x5,x6,x7,x8] | x1<-[1..8], x2<-[1..8],
                          x3<-[1..8], x4<-[1..8], x5<-[1..8],
                          x6<-[1..8], x7<-[1..8], x8<-[1..8],
                          safeH [x2,x3,x4,x5,x6,x7,x8] x1]
safeH xs e = if length xs == 1 then head xs 
                 else e /= safeH (tail xs) (head xs)

and the error message is:

y.hs:1:42:
    No instance for (Num Bool) arising from the literal `1'
    Possible fix: add an instance declaration for (Num Bool)
    In the expression: 1
    In the expression: [1 .. 8]
    In a stmt of a list comprehension: x1 <- [1 .. 8]
[1 of 1] Compiling Main             ( y.hs, interpreted )
Failed, modules loaded: none.
Was it helpful?

Solution 2

The if ... then ... else ... expression in safeH is not well-typed:

safeH l e = if length l == 1 then head l 
            else e /= safeH(tail l)(head l)

The then branch is incorrectly returning a numeric type, while the else branch is returning a boolean type Bool, as I think you intended.

You should add type signatures to all your top-level functions as a way of documenting what your code does, organizing your thoughts, and making errors easy to understand; the error message here is needlessly confusing because GHC infers that your code is returning some Num type thing from the first branch, and so when the second branch returns Bool GHC complains about the wrong thing: there being no instance of Num for the Bool type).

You should also read about pattern matching on lists, and take a look at the implementation of length and think about why it's not the best way to implement your function here.

So instead of using length and head, start with this framework:

safeH :: [Int] -> Int -> Bool
safeH [n]    e = -- the case for a 1-length list
safeH (n:ns) e = -- ???

When you get something working then try redefining it where the base case is the empty list [].

OTHER TIPS

The culprit is

                      .........
                      safeH [x2,x3,x4,x5,x6,x7,x8] x1]
safeH xs e = if length xs == 1 then head xs 
                 else e /= safeH (tail xs) (head xs)

specifically,

                 else e /= safeH (tail xs) (head xs)

because e == x1. So on the one hand safeH returns Bool, being used as a test in the list comprehension. OTOH you compare its result with x1. Which is 1, among other things (x1<-[1..8]). I.e. Num1. Which must also be a Bool. Hence the error.


1 A numeric literal such as 1 is parsed as a value of a polymorphic type Num a => a. I.e. its concrete type must belong to the Num type class. Since the concrete type is also determined to be Bool here, this means that Bool must belong to the Num type class, for this code to typecheck. Hence the instance for (Num Bool) is sought.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top