Haskell中有8个皇后,未知错误?

时间:2013-08-19 19:23:59

标签: haskell haskell-platform

我试图在没有使用任何高级功能的情况下解决Haskell中的8个皇后问题,只有基本知识。我只走到这一步,但我得到一个我无法理解的错误。 代码:

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)

,错误信息为:

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.

2 个答案:

答案 0 :(得分:5)

罪魁祸首是

                      .........
                      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)

具体而言,

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

因为e == x1。所以一方面safeH返回Bool,用作列表理解中的测试。 OTOH你将其结果与x1进行比较。其中包括1,(x1<-[1..8])。即Num 1 。哪个也必须是Bool。因此错误。


1 1等数字文字解析为多态类型Num a => a的值。即其具体类型必须属于Num类型类。由于具体类型在此处也被确定为Bool,这意味着Bool必须属于Num类型类,此代码要进行类型检查。因此寻求instance for (Num Bool)

答案 1 :(得分:4)

if ... then ... else ...中的safeH表达式输入效果不佳:

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

then分支错误地返回数字类型,而else分支返回布尔类型Bool,正如我认为的那样。

您应该为所有顶级功能添加类型签名,以记录代码的作用,组织您的想法,并使错误易于理解;这里的错误消息是不必要的混淆因为GHC推断你的代码从第一个分支返回一些Num类型的东西,所以当第二个分支返回Bool时GHC抱怨错误的东西:没有Num类型的Bool实例。

您还应该阅读关于列表中的pattern matching,并查看implementation of length并考虑一下为什么它不是在这里实现您的功能的最佳方式。

因此,不要使用lengthhead,而应使用此框架:

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

当你得到一些工作后,尝试重新定义基础案例为空列表[]的地方。