0

我正在尝试在不使用任何高级功能的情况下解决 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.
4

2 回答 2

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])。即Num1。这也必须是一个Bool. 因此错误。


1一个数字文字,如1被解析为多态类型的值Num a => a。即它的具体类型必须属于Num类型类。由于这里也确定了具体类型Bool,这意味着它Bool必须属于Num类型类,才能让这段代码进行类型检查。因此instance for (Num Bool)寻求。

于 2013-08-19T19:47:15.243 回答
4

中的if ... then ... else ...表达式safeH不是很好的类型:

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

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

您应该将类​​型签名添加到所有顶级函数中,以记录您的代码所做的事情、组织您的想法并使错误易于理解;这里的错误消息是不必要的混乱,因为 GHC 推断您的代码正在Num从第一个分支返回某种类型的东西,所以当第二个分支返回时,BoolGHC 抱怨错误的东西:没有NumBool类型的实例)。

您还应该阅读列表上的模式匹配,并查看实现length并思考为什么它不是在这里实现您的功能的最佳方式。

因此,不要使用lengthand head,而是从这个框架开始:

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

当您得到一些工作时,请尝试在基本情况为空列表的情况下重新定义它[]

于 2013-08-19T19:53:40.963 回答