Home > database >  Union of Data.Map.fromList could not match type in Haskell
Union of Data.Map.fromList could not match type in Haskell

Time:10-17

I am fairly new to Haskell and trying to create a game board of the game Reversi (Othello). Thereafter, I want to use this to return a starting Player and the initial starting position of the board. So two issues.

  1. Generate game plan

I have two data types for the different Players and possible moves to make.

data Player = Black | White
  deriving (Eq,Show)

{- Game moves.
   Pass represents a passing move. Move i represents a move to field i.
   INVARIANT: 0 <= i <= 63 in Move i
 -}
data Move = Pass | Move Int
  deriving (Eq,Show)

My initial idea was to create an Associated list (dictionary) where each key value pair makes up a field on the board. So the key would be (0...63) and the values could be Black/White or empty. However, the Player data type cannot be modified to include e.g, Empty.

To play the game, I need to create a function that returns which player that starts and the initial board. The starting position should look like this:

Start position

So I was thinking I could use Haskell's built in Data.Map to create an empty board and then create the initial position and then union these two to obtain a complete game board with the starting position.

fields :: [Integer]
fields = [x | x <- [1 .. 63]]

type Field = Maybe Player

emptyBoard :: Data.Map.Map Integer (Maybe a)
emptyBoard = Data.Map.fromList (zip fields (repeat Nothing))

startBoard =
  Data.Map.fromList
    [ (27, White),
      (36, White),
      (28, Black),
      (35, Black)
    ]

initialBoard = Data.Map.union startBoard emptyBoard

Following this way of thinking about the board:

enter image description here

However, when running this in the Prelude, I get:

<interactive>:42:45: error:
    * Couldn't match type `Maybe a0' with `Player'
      Expected type: Data.Map.Internal.Map k Player
        Actual type: Data.Map.Internal.Map k (Maybe a0)
    * In the second argument of `Data.Map.Internal.union', namely
        `emptyBoard'
      In the expression: Data.Map.Internal.union startBoard emptyBoard
      In an equation for `initialBoard':
          initialBoard = Data.Map.Internal.union startBoard emptyBoard

How can I go about creating an emptyBoard with the same type as in startBoard?

  1. Initial position

My second issue is to create a state of the game. So, something like this.

-- Board consists of tuples with integers and Player or empty
data Board = Board [(Integer, Field)]
-- type State = () is required to be a type synonym 
type State = (Player, Board)  

So that when creating my function to generate the initial game, with something like this:

initial :: Player -> State
initial p = if p == Black then (Black, initialBoard) else (White, initialBoard)

The type declaration of initial cannot be changed. Nevertheless, I get a warning from the intellisense:

• Couldn't match expected type ‘Board’
              with actual type ‘Data.Map.Map k0 Player’
• In the expression: initialBoard 

So, in summary. 1) how can I generate a startBoard with only the middle fields populated and the rest empty and 2), the initial game plan with a player and the boards starting position.

CodePudding user response:

how can I generate a startBoard with only the middle fields populated and the rest empty

The startBoard you wrote works perfectly for that. Don't overthink things. Throw away emptyBoard and initialBoard entirely. Representing empty squares by simply not having that key in the Map is going to be simpler than having an explicit key that maps to Nothing anyway.

how can I generate the initial game plan with a player and the boards starting position

Ya just tuple 'em up.

type State = (Player, Map Integer Player)

initial :: Player -> State
initial p = (p, startBoard)
  • Related