如何在Haskell中通过map传递函数

时间:2016-12-02 02:56:32

标签: haskell

我一直在寻找这个问题的答案,但无济于事。我试图弄清楚如何将它映射到bs后,从checkconsec中的行传递第一个数组。我试图使用xs但它不起作用。谁能看到我做错了什么?

import Data.Maybe
import Data.List

data Piece = Yellow | Red deriving Eq
type Column = [Piece]
type Board = [Column]

data BoardState = BS {
theBoard :: Board,
lastMove :: Piece,
numColumns :: Int,
numRows :: Int, 
numToConnect :: Int}

---------- Make Move -----------
-- This function makes a move on a Boardstate, first checks if the column is full or if the column exists or not.
-- If true returns just a boardstate, if false returns nothing
makeMove :: BoardState -> Int -> Maybe BoardState   
makeMove bs n = case ((checkLegal bs n) && (checkNotFull bs (columns bs !! (n-1)))) of
         True -> Just (updateBoard bs n)                                
         False -> Nothing

-- Checks if the move is legal, i.e. if the column to be moved into exists
checkLegal :: BoardState -> Int -> Bool
checkLegal bs i = case (i <= (numColumns bs) && (i /= 0)) of
           True -> True
           False -> False

-- Checks if the desired column is not full.
checkNotFull :: BoardState -> [Maybe Piece] ->Bool
checkNotFull bs a  = case (length (catMaybes a)< (numRows bs)) of
         True ->True
         False -> False


-----------Parts of Board-----------
-- This function repeats nothing over and over.
repeatNothing :: Int -> [Maybe a]
repeatNothing m = replicate m Nothing

-- This function pads a list so that the resulting list is of the appropriate length
padN :: [a] -> Int -> [Maybe a]
padN xs n = (map Just xs) ++ repeatNothing (n - (length xs))

-- This function finds all of the columns of the board
columns :: BoardState -> [[Maybe Piece]]
columns bs = map (\col -> padN col (numRows bs)) (theBoard bs) 

-- This function finds all the rows of the board
rows :: BoardState -> [[Maybe Piece]]
rows bs = map (\col -> padN col (numRows bs)) (transpose(theBoard bs))

-- This function will find the forward diagonals, but first gets the rows and the calls diagonals on the already padded
-- rows
diagonalsForward :: BoardState -> [[Maybe Piece]]
diagonalsForward bs = (diagonals (rows(bs)))

-- This function will find the backward diagonals, but first the rows are found, then the resulting grid is rotated
-- 90 degrees, followed by calling diagonals, which will then return the backwards diagonals, however in the wrong order
-- so then reverse is called on each list in order to get the correct order of the diagonals
diagonalsBackward :: BoardState -> [[Maybe Piece]]
diagonalsBackward bs = map reverse (diagonals((map reverse.transpose)(rows(bs))))

-- Because this section of code is cited above, the detailed axplanation of how it works is attached in another document
diagonals :: [[t]] -> [[t]]
diagonals [] = []
diagonals ([]:xss) = xss
diagonals xss = zipWith (++) (map ((:[]).head) xss ++ repeat[])
        ([] : (diagonals (map tail xss)))

-----------Check Win ---------------

checkWin :: BoardState -> [[Maybe Piece]]
checkWin bs = map (checkConsec bs) (rows bs)

checkConsec :: BoardState -> [[Maybe Piece]] -> [Maybe Piece]
checkConsec bs (x:xs) = helper (numToConnect bs) 1 (lastMove bs) x

helper :: Int -> Int -> Piece  -> [Maybe Piece] -> [Maybe Piece]
helper = undefined

{-
helper numToCon cntr color (x:xs) = [];
helper numToCon cntr color (x:xs) = if cntr 0 then Nothing -- cntr initialized to 1
else case (color, x) of
(Just Yellow, Just Yellow) -> helper numToCon (cntr+1) color
(Just Yellow, Nothing) -> helper numToCon(cntr=1) color
(Just Yellow, Just Red) -> helper numToCon(cntr=1) color
(Just Red, Just Red) -> helper numToCon(cntr+1) color
(Just Red, Nothing) -> helper numToCon(cntr=1) color
(Just Red, Just Yellow) -> helper numToCon(cntr=1) color
-}

---------Update Board------------
-- This function splits a list into three separate pieces, the position of the split is determined by the parameter n 
split3:: Int -> [Column] -> ([Column], Column, [Column])
split3 n xs = let (ys,(z:zs)) = (take (n-1) xs, drop (n-1) xs) in (ys, z, zs)

-- Calls split3 on the board 
splitBoard :: BoardState -> Int -> [Column]
splitBoard bs n = addPiece bs (split3 n (theBoard bs))

-- Adds a piece to the desired column of the board
addPiece :: BoardState -> ([Column], Column, [Column]) -> [Column]
addPiece bs (x,y,z) = x ++ (y ++ [lastMove bs]):z 

-- Updates the board to the new state, after adding a piece (or not) and updating the lastMove 
updateBoard :: BoardState -> Int -> BoardState
updateBoard bs n = case (lastMove bs) of
           Yellow -> BS {theBoard = splitBoard bs n,
       lastMove = Red,  
       numColumns = numColumns bs,
       numRows = numRows bs,    
       numToConnect = numToConnect bs}
           Red -> BS {theBoard = splitBoard  bs n,
       lastMove = Yellow,
       numColumns = numColumns bs,
       numRows = numRows bs,
       numToConnect = numToConnect bs}

**编辑:我已对此进行了编辑,以包含我的所有代码,希望这样可以更轻松地理解我的问题。我还修复了(据我所知)checkconsec和helper的类型。我现在唯一的错误是:

Couldn't match type ‘Maybe Piece’ with ‘[Maybe Piece]’
    Expected type: [[[Maybe Piece]]]
      Actual type: [[Maybe Piece]]
    In the second argument of ‘map’, namely ‘(rows bs)’
    In the expression: map (checkConsec bs) (rows bs)
Failed, modules loaded: none.

1 个答案:

答案 0 :(得分:2)

函数的参数由空格分隔。 foo a b c将三个参数应用于foofoo (a b) c将两个参数应用于foo。函数应用程序具有最高优先级。我没有你剩下的代码,但我猜你的意思如下。

checkWin :: BoardState -> [[Maybe Piece]]
checkWin bs = map (checkConsec bs) (rows bs)

checkConsec :: BoardState -> [Maybe Piece] -> [Maybe Piece]
checkConsec bs = helper (numToConnect bs) 1 (lastMove bs) xs 

helper :: Int -> Int -> Maybe Piece -> [Maybe Piece] -> [Maybe Piece]
helper = undefined