簡體   English   中英

將函數名稱更改為列表時出錯,haskell

[英]Error when changing function name to list, haskell

我幾乎完成了我的代碼,但我必須做一些輕微的修改。 這是我的代碼:

module Sudoku where

import Data.Char
import Data.List
import Data.Maybe

import Test.QuickCheck

data Sudoku = Sudoku { rows :: [[Maybe Int]] }
  deriving (Show, Eq) 

example :: Sudoku
example =   Sudoku [[Just 3, Just 6, Nothing,Nothing,Just 7, Just 1, Just 2, Nothing,Nothing]
    , [Nothing,Just 5, Nothing,Nothing,Nothing,Nothing,Just 1, Just 8, Nothing]
    , [Nothing,Nothing,Just 9, Just 2, Nothing,Just 4, Just 7, Nothing,Nothing]
    , [Nothing,Nothing,Nothing,Nothing,Just 1, Just 3, Nothing,Just 2, Just 8]
    , [Just 4, Nothing,Nothing,Just 5, Nothing,Just 2, Nothing,Nothing,Just 9]
    , [Just 2, Just 7, Nothing,Just 4, Just 6, Nothing,Nothing,Nothing,Nothing]
    , [Nothing,Nothing,Just 5, Just 3, Nothing,Just 8, Just 9, Nothing,Nothing]
    , [Nothing,Just 8, Just 3, Nothing,Nothing,Nothing,Nothing,Just 6, Nothing]
    , [Nothing,Nothing,Just 7, Just 6, Just 9, Nothing,Nothing,Just 4, Just 3]
    ]

-- A

-- Crates a blank sudoku "map"
allBlankSudoku :: Sudoku
allBlankSudoku = Sudoku (replicate 9 (replicate 9 Nothing)) 

-- Checks if the criterias meet the standard sudoku
isSudoku :: Sudoku -> Bool
isSudoku x = (length (rows x) == 9) && ( and [length y == 9 | y <- rows x]) && ( and [x > 0 && x < 10 | Just x <- concat (rows x)])

-- Checks if the sudoku puzzle is solved. Which is when there is no more cells to fill in
isSolved :: Sudoku -> Bool
isSolved x = Nothing `notElem` concat (rows x)

-- Prints a sudoko
printSudoku :: Sudoku -> IO()
printSudoku x = putStr (unlines ([ map convertInt y | y <- rows x]))

-- converting from int to char 
convertInt :: Maybe Int -> Char 
convertInt Nothing = '.'
convertInt (Just x) = chr (x+48)

-- simply reads sudoku from file
readSudoku :: FilePath -> IO Sudoku 
readSudoku x = 
        do y <- readFile x
           return (Sudoku [map convertChar c | c <- lines y])

-- Convertion from char to int.       
convertChar :: Char -> Maybe Int
convertChar '.' = Nothing
convertChar x  = Just (digitToInt x)

-- this function crates a cell
cell :: Gen (Maybe Int) 
cell  = frequency
        [(1, do n <- choose (1,9)
                return (Just n)),
            (9, return Nothing)]

 -- C2. Make Sudokus an instance of the class Arbitrary.
instance Arbitrary Sudoku where
  arbitrary =
    do rows <- sequence [ sequence [ cell | j <- [1..9] ] | i <- [1..9] ]
       return (Sudoku rows)

-- check sudoku
prop_Sudoku :: Sudoku -> Bool
prop_Sudoku x = isSudoku x

type Block = [ Maybe Int]

-- CHeck if block containts same digit twice
isOkayBlock :: Block -> Bool
isOkayBlock x = x' == nub x'
            where x' = filter isJust x

-- create list of all blocks
blocks :: Sudoku -> [Block]
blocks x = rows x ++ transpose (rows x) ++ blocks1 x

-- 3x3 made by blocks
blocks1 :: Sudoku -> [Block] 
blocks1 x = [concat [take 3 (drop a b) | b <- take 3 (drop d (rows x))] | a <- [0,3,6] , d <- [0,3,6]]

-- checks the whole sudoku
isOkay :: Sudoku -> Bool
isOkay x = and (map isOkayBlock (blocks x))
prop_isOkay x = and [ length a == 9 | a <- blocks x ] && length (blocks x) == 27


type Pos = (Int,Int)

blanks :: Sudoku -> Pos
blanks = head . allBlanks

-- Changed the way blanks works,
(!!!) :: [[a]] -> Pos -> a
(!!!) l (y,x) = (l !! y) !! x

-- Get the blanks in sudoku.
allBlanks :: Sudoku -> [Pos]
allBlanks s = [ (y,x) | y <- [0..8], x <- [0..8], ((rows s) !!! (y,x)) == Nothing]

prop_isBlank :: Sudoku -> Bool
prop_isBlank sud = (selElement (selectRow (rows sud) x) y) == Nothing
   where (x, y) = blanks sud

selectRow :: [[a]] -> Int -> [a]
selectRow (x:_) 0  = x
selectRow (x:xs) n = selectRow xs (n-1)

selElement :: [a] -> Int -> a
selElement (x:_) 0  = x
selElement (x:xs) n = selElement xs (n-1)


--Replace/update 
(!!=) :: [a] -> (Int ,a) -> [a] 
(x:xs) !!= (0,a) = (a:xs)
(x:xs) !!= (y,a) = (x:(xs!!=(y-1,a)))

prop_replacedElement :: [Int] -> (Int,Int) -> Property
prop_replacedElement list (index, obj) = list /= [] ==> (list !!= (index', obj)) !! index' == obj
  where
    index' = index `mod` length list

-- Update cell with new value
update :: Sudoku -> Pos -> Maybe Int -> Sudoku
update x (p,i) y = Sudoku ((rows x) !!= (p,z))
                   where z = (rows x) !! p !!= (i,y) 

-- Check update function
prop_update (x,y) sud n = prop_XY (x',y') (update sud (x',y') n) == n 
                          where x' = x `mod` 9 
                                y' = y `mod` 9

-- helepr to find specific value 
prop_XY (x,y) sud = ((!!) (rows (sud)) x) !! y


-- Gives allowed numbers on an empty cell
candidates :: Sudoku -> Pos -> [Int]
candidates sud (x,y) = filter (/=0) [if isOkay (update sud (x,y) (Just z)) == True then z else 0 | z <- [1..9]]


solve :: Sudoku -> Maybe Sudoku
solve  x 
       | not(isOkay x) = Nothing
       | isSolved x = Just x
       | otherwise = solve' [solve $ update x (blanks x) (Just c) | c <- [1..9]]

-- take from our list solutions
solve' :: [Maybe a] -> Maybe a 
solve' [] = Nothing
solve' (Nothing:xs) = solve' xs
solve' (Just x:xs) = Just x 

-- read and solves the sudoku. 
readAndSolve :: FilePath -> IO () 
readAndSolve x = do 
  y <- readSudoku x
  case solve y of
      Nothing  -> putStrLn"(no solution)"
      Just y -> printSudoku y

-- check if x 2 solution to x1
isSolutionOf :: Sudoku -> Sudoku -> Bool
isSolutionOf x1 x2 = isOkay x1 && isSolved x1 && isSolutionOf2 (zip (concat(rows x1)) (concat(rows x2)))

-- helper func
isSolutionOf2 :: (Eq a) => [(Maybe a, Maybe a)] -> Bool 
isSolutionOf2 [] = True
isSolutionOf2 ((x,y):xs) = x == y || y == Nothing && isSolutionOf2 xs

-- Solved or not 
prop_SolveSound :: Sudoku -> Property
prop_SolveSound x = isOkay x ==> (fromJust (solve x)) `isSolutionOf` x 

現在我必須更改功能:

blanks :: Sudoku -> Pos

到:

blanks :: Sudoku -> [Pos]

但是這樣做時,我會遇到一些我不知道如何解決的錯誤。 我試圖改變,以便在我的解決定義中使用函數“head”。 代碼示例表示贊賞。

編輯

忘記輸入錯誤:

Sudoku.hs:99:10: error:
    • Couldn't match type ‘(Int, Int)’ with ‘[Pos]’
      Expected type: Sudoku -> [Pos]
        Actual type: Sudoku -> Pos
    • In the expression: head . allBlanks
      In an equation for ‘blanks’: blanks = head . allBlanks

Sudoku.hs:111:19: error:
    • Couldn't match expected type ‘(t, t1)’ with actual type ‘[Pos]’
    • In the expression: blanks sud
      In a pattern binding: (x, y) = blanks sud
      In an equation for ‘prop_isBlank’:
          prop_isBlank sud
            = (selElement (selectRow (rows sud) x) y) == Nothing
            where
                (x, y) = blanks sud
    • Relevant bindings include
        x :: t (bound at Sudoku.hs:111:11)
        y :: t1 (bound at Sudoku.hs:111:14)

Sudoku.hs:155:48: error:
    • Couldn't match type ‘[Pos]’ with ‘(Int, Int)’
      Expected type: Pos
        Actual type: [Pos]
    • In the second argument of ‘update’, namely ‘(blanks x)’
      In the second argument of ‘($)’, namely
        ‘update x (blanks x) (Just c)’
      In the expression: solve $ update x (blanks x) (Just c)
Failed, modules loaded: none.

第一個錯誤告訴您新的blanks定義是錯誤的。 原因是應用於[Pos] head返回Pos ,這與您想要返回的類型不同。

您在兩種情況下使用blanks

  1. 在模式綁定中: (x, y) = blanks (第二個錯誤)
  2. update的第二個參數中,即(blanks x) (第三個錯誤)

blanks函數的這兩種用法要求它返回一個Pos

我建議:

  1. 不要更改函數類型,而是將blanks重命名為firstBlank或更有意義的名稱
  2. 完全刪除blanks並將其替換為head . allBlanks head . allBlanks

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM