Reputation: 489
I'm making my a minesweeper (game) instead of using a list of list as representation, I'm using different sets that will keep the cells collected by their type.
I'm trying to generate a Map which uses as keys a tuple (x coordinate, y coordinate) as a pair for example like this (0,0). The value of the map will be the amount of neighbors containing a bomb. for example (0,0) 1 meaning cell (0,0) has 1 neighbors with a bomb.
I was able to come up with a dirty way to make it although I'm getting an error on the Map.empty.
Error
setTest.hs:57:70:
Couldn't match expected type `Map.Map (t0, t0) Int
-> Map.Map (t0, t0) Int'
with actual type `Map.Map k0 a1'
In the second argument of `createBoard', namely `Map.empty'
In the expression: createBoard listOfBombs Map.empty fieldList
In the expression:
let
fieldList = [... | x <- ..., y <- ...]
nrBombs = round $ fromIntegral (xCoord * yCoord) * 0.20
listOfBombs
= Set.fromAscList
(take nrBombs
$ nub $ randomRs ((0, 0), (xCoord, yCoord)) (mkStdGen seed))
in createBoard listOfBombs Map.empty fieldList
Failed, modules loaded: none.
I do understand that the error appears because of the Map.empty having another type than the Map that I use in my functions. However I can not find a way to solve this issue? Also I there a way to link those function smoother together using Map/fold or zip?
--Generate Set with all the neighbors of a cell
neighbours (xCoord,yCoord) = Set.fromAscList $ filter (/=(xCoord,yCoord)) [(x,y) | x <- [(pred xCoord) .. (succ xCoord)], y <- [(pred yCoord) .. (succ yCoord)]]
--Gives back the number of neighbors with a bomb for a cell
giveBackBombsNumber (xCoord,yCoord) listOfBombs = Set.size $ Set.intersection (neighbours (xCoord,yCoord)) listOfBombs
-- Will insert a cell with the number of bombs around it to the board map.
insertFunction field listOfBombs board = Map.insert field (giveBackBombsNumber field listOfBombs) board
-- Will create a new Map containing
createBoard listOfBombs board [] = board
createBoard listOfBombs board (x: xs) = createBoard listOfBombs (insertFunction x listOfBombs) xs
testFunction (xCoord,yCoord) seed = let fieldList = [(x,y) | x <- [0 .. xCoord] , y <- [0 .. yCoord]]
nrBombs = round $ fromIntegral (xCoord * yCoord) * 0.20
listOfBombs = Set.fromAscList (take nrBombs $ nub $ randomRs ((0,0), (xCoord,yCoord)) (mkStdGen seed))
in createBoard listOfBombs Map.empty fieldList
Upvotes: 0
Views: 494
Reputation: 85827
Ignoring the details, your error message reads:
Couldn't match expected type `X -> Y'
with actual type `Map.Map k0 a1'
i.e. you're using a Map
where the code is expecting a function instead.
Likely culprit:
createBoard listOfBombs board (x: xs) = createBoard listOfBombs (insertFunction x listOfBombs) xs
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You're calling insertFunction
with 2 arguments, but it takes 3.
Because of currying, insertFunction x listOfBombs
is itself a function (\board -> Map.insert field (giveBackBombsNumber field listOfBombs) board
), and you're passing it as the second argument to createBoard
(which is board
), so ghc thinks board
is supposed to be a function and rejects your attempt to give it a Map
.
You'll get much better error messages if you put explicit type annotations on your functions.
Upvotes: 5