相关类型:
Data Sudoku = Sudoku [[Maybe Int]]
type Block = [Maybe Int]
rows :: Sudoku -> [[Maybe Int]]
rows (Sudoku rs) = rs
我有一份清单,[[可能是国际]],我已经说过了
type Block = [Maybe Int]
我正在进行的任务是创建一个数独求解器,所以我需要一个函数来返回一个空白的位置'细胞,空白没什么。 数独的实际布局是
Sudoku [
, list1
, list2
.... ]
直到我有九个列表,每个列表包含九个元素,Nothing或Just Int。
type Pos = (Int, Int)
Pos中的第一个Int应该指出哪个' row'包含空白单元格。第二个应该指出该行中哪个元素是空白元素。 我已经写过
了whichRow :: Sudoku -> Int
whichRow (Sudoku (x:xs)) =
if isNothingPresent x == False then 1 + whichRow (Sudoku xs) else 1
whereIsNothing :: Block -> Int
whereIsNothing (x:xs) = if x == Nothing then 1 else 1 + whereIsNothing xs
isNothingPresent :: Block -> Bool
isNothingPresent b
| Nothing `notElem` b = False
| otherwise = True
现在我需要组合这些函数并创建一个函数空白,它将检查数独并返回空白单元格的位置。我玩了一遍并尝试过:
blank :: Sudoku -> Pos
blank sud = do k <- (whichRow sud)
n <- (whereIsNothing (head (drop (k-1) (rows sud))))
(return (k, n))
这显然是错误的,我得到了类型错误和各种各样的东西。并且在那里看起来很糟糕。有人能指出我正确的方向吗?谢谢!
我收到这些错误:
Sudoku.hs:159:22:
Couldn't match expected type `(Int, Int)' with actual type `Int'
In a stmt of a 'do' block: k <- (whichRow sud)
In the expression:
do { k <- (whichRow sud);
n <- (whereIsNothing (head (drop (k - 1) (rows sud))));
(return (k, n)) }
Sudoku.hs:160:22:
Couldn't match expected type `(Int, t0)' with actual type `Int'
In a stmt of a 'do' block:
n <- (whereIsNothing (head (drop (k - 1) (rows sud))))
In the expression:
do { k <- (whichRow sud);
n <- (whereIsNothing (head (drop (k - 1) (rows sud))));
(return (k, n)) }
Sudoku.hs:161:24:
Couldn't match expected type `Int' with actual type `(Int, t0)'
Relevant bindings include n :: t0 (bound at Sudoku.hs:160:16)
In the first argument of `return', namely `(k, n)'
In a stmt of a 'do' block: (return (k, n))
In the expression:
do { k <- (whichRow sud);
n <- (whereIsNothing (head (drop (k - 1) (rows sud))));
(return (k, n)) }
再次编辑:另外我很确定如果没有空白单元格,这个函数会表现得很有趣。
答案 0 :(得分:3)
首先,使用tail-recursive,但不使用递归函数。
whichRow :: Sudoku -> Int
whichRow s = whichRow' s 0 -- tail-recursive
where
whichRow' (Sudoku (x:xs)) i = if isNothingPresent x
then 1
else whichRow' (Sudoku xs) (i+1)
第二个,不要忘记在模式匹配时查看所有案例:
whichRow :: Sudoku -> Int
whichRow s = whichRow' s 0
where
whichRow' (Sudoku []) i = i -- missing case
whichRow' (Sudoku (x:xs)) i = if isNothingPresent x
then 1
else whichRow' (Sudoku xs) (i+1)
第三,为什么要使用这么多括号?
blank :: Sudoku -> Pos
blank sud = do k <- whichRow sud
n <- whereIsNothing (head (drop (k-1) (rows sud)))
return (k, n)
但 MAIN - 此代码无效。 do
是monad,但您只使用Int
。请改用let
blank :: Sudoku -> Pos
blank sud = let k = whichRow sud in
let n = whereIsNothing $ head $ drop (k-1) (rows sud) in
(k, n)
或where
blank :: Sudoku -> Pos
blank sud = (k, n)
where
k = whichRow sud
n = whereIsNothing $ head $ drop (k-1) (rows sud)
第四次,不要重复使用很多Bool
,例如if smth == True then ....
,而是写if smth then ...
。我们来看看
isNothingPresent :: Block -> Bool
isNothingPresent b
| Nothing `notElem` b = False
| otherwise = True
我们可以将其重写为
isNothingPresent :: Block -> Bool
isNothingPresent b = not $ Nothing `notElem` b
或者更简单地说
isNothingPresent :: Block -> Bool
isNothingPresent b = Nothing `elem` b