我试图在没有使用任何高级功能的情况下解决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.
答案 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
并考虑一下为什么它不是在这里实现您的功能的最佳方式。
因此,不要使用length
和head
,而应使用此框架:
safeH :: [Int] -> Int -> Bool
safeH [n] e = -- the case for a 1-length list
safeH (n:ns) e = -- ???
当你得到一些工作后,尝试重新定义基础案例为空列表[]
的地方。