【问题标题】:Error:Dividing by Zero (Haskell)错误:除以零(Haskell)
【发布时间】:2015-06-25 13:43:55
【问题描述】:

我正在尝试编写一个程序来确定如果棋盘上有 2 个皇后,8x8 棋盘的哪些位置可以安全地放置一个马。

函数的输入是[0, 0, 6, 0, 0, 4, 0, 0],所以它被称为knightPlace [0, 0, 6, 0, 0, 4, 0, 0]。所有非零都是皇后。

如您所见,列表的第 3 和第 6 个元素是 6 和 4,这导致皇后位于第 3 列和第 6 行和第 6 列和第 4 行(假设您从底部的 0,0 开始棋盘的左角)。

我的 col 和 row 检查过滤得很好,但我的 diagCheck 带来了一个新的错误消息:

knightPlace[0, 0, 6, 0, 0, 4, 0, 0]
*** Exception: divide by zero

有人可以帮帮我吗?它永远不应为 0,因为 diagCheck 解决了皇后和另一个坐标的斜率,使其为假,因此如果斜率为 == 1 或 -1 则不添加

这是我使用的代码:

knightPlace n = makeboard n 
    where 
    makeboard n = [(i + 1,j + 1) | i<-[0..(length n -1 )], j<-[0..(length n - 1)], colrowcheck n i j]
    -- col and row check, if the condition ==FALSE it doesnt get added 
    colrowcheck n i j = and [(n!!(i) == 0) && n!!(k) /=(j+1)| k<-[0..(length n -1 )], not(diagcheck n i j k) ] 

    -- diagcheck
    diagcheck n i j k = ((j+1) - n!!(k)) `div` ((i+ 1) - k)  == -1 || ((j+1) - n!!(k)) `div` ((i+1) - k)  == 1

【问题讨论】:

  • 要将div用作中缀函数,您必须将其括在反引号中:(j - n!!(k)) `div` (i - k)
  • 哇,好吧,我解决了这个问题,但现在它说我除以零,我会相应地改变问题
  • 你应该提出一个新问题而不是改变这个问题,这样你就不会使答案无效。

标签: haskell types int


【解决方案1】:

(这回答了 OP 在编辑之前发布的原始问题。)

这看起来不对:

(j - n!!(k)) div (i - k)  == -1 || (j - n!!(k)) div (i - k)  == 1

尝试添加一些反引号:

(j - n!!(k)) `div` (i - k)  == -1 || (j - n!!(k)) `div` (i - k)  == 1

题外话:上面也可以改写成

((j - n!!k) `div` (i - k)) `elem` [-1,1]

回到主题:要改进 GHC 错误消息,请尝试为您的函数添加一些类型注释。例如

knightPlace :: Int -> [(Int,Int)]
knightPlace n = makeboard n 
    where 
    makeboard n = [(i + 1,j + 1) | i<-[0..(length n -1 )], j<-[0..(length n - 1)], colrowcheck n i j]

    colrowcheck :: [Int] -> Int -> Int -> Bool
    colrowcheck n i j = and [(n!!(i) == 0) && n!!(k) /=(j+1)| k<-[0..(length n -1 )], diagcheck n i j k ] 

    -- diagcheck
    diagcheck :: [Int] -> Int -> Int -> Int -> Bool
    diagcheck n i j k = (j - n!!(k)) `div` (i - k)  == -1 || (j - n!!(k)) `div` (i - k)  == 1

添加这些类型注释可以让 GHC 及早检测到类型错误。在您的原始代码中,sn-p

(j - n!!(k)) div (i-j) == -1

计算j - n!!k,然后将其视为接受两个参数的函数,即div 和i-j。 GHC 推断出j - n!!k 的函数类型并继续前进。 diagcheck 中没有类型错误,但是一旦您尝试使用整数列表而不是函数列表调用 diagcheck,它们就会弹出。

【讨论】:

  • 添加类型注释会使每个函数都失败,我不知道为什么,但我认为大多数是因为:无法匹配预期类型[Int]' with actual type Int' 无法匹配预期类型[a0]' with actual type Int'什么是类型[a0]
  • @REALLYANGRYSTUDENT 我将注释更改为我认为正确的注释。随意尝试它们并使用符合您直觉的任何内容:如果您知道参数是整数列表,请使用[Int],依此类推。
猜你喜欢
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多