Search code examples
haskellalgebraic-data-types

Can I include data declaration to another data?


I am writing CodinGame hypersonic bot.

I have a working code for parse input

type Position = (Int,Int)

data Entity = Player { pId :: Int, pPos :: Position, pBombStock :: Int, pBombRange :: Int } 
            | Bomb { bOwnerId :: Int, bPos :: Position, bTimeLeft :: Int , bBombRange :: Int}
  deriving Show

-- The entityType will be:
--   For players: 0.
--   For bombs: 1.
-- The owner will be:
--   For players: id of the player ( 0 or 1).
--   For bombs: id of the bomb's owner.
-- The param1 will be:
--   For players: number of bombs the player can still place.
--   For bombs: number of rounds left until the bomb explodes.
-- The param2 is not useful for the current league, and will always be:
--   For players: explosion range of the player's bombs (= 3).
--   For bombs: explosion range of the bomb (= 3).
mkEnt :: Int -> Int -> Int -> Int -> Int -> Int -> Entity
mkEnt 0 o x y p1 p2 = Player { pId = o, pPos = (x,y), pBombStock = p1, pBombRange = p2}
mkEnt 1 o x y p1 p2 = Bomb { bOwnerId = o, bPos = (x,y), bTimeLeft = p1, bBombRange = p2}
mkEnt _ _ _ _ _  _  = error "invalid entity type"

main :: IO ()
main = do
  print $ mkEnt 0 1 0 0 0 3
  print $ mkEnt 1 1 0 0 0 3

But when I try to refactor the Entity

data Entity = Player | Bomb
  deriving Show

data Player = Player { pId :: Int, pPos :: Position, pBombStock :: Int, pBombRange :: Int } 
  deriving Show

data Bomb = Bomb { bOwnerId :: Int, bPos :: Position, bTimeLeft :: Int , bBombRange :: Int}
  deriving Show

the code won't compile with error: Multiple declarations of ‘Player’

Do I need any language extension to make this work, or it can not be done (by designed).


Solution

  • You have two constructors in the same module called Player, and the same with Bomb. You could give one of them a prefix like this to disambiguate the constructors:

    data Entity = EPlayer | EBomb
      deriving Show
    

    However, I don't think your Entity is doing quite what you want it to do. Those two constructors on Entity carry no data and have no relation to the data types Player and Bomb. If you wanted the Entity constructors to carry data, you could define them as such:

    data Entity = EPlayer Player | EBomb Bomb
      deriving Show
    

    But by that then, you are kind of in the same position where you started. What exactly are you trying to achieve by this refactoring?