title: Haskell - resolving cyclical module dependency
body: <p>Let's say I write the following code:</p>
  
  <p>a game module</p>
  
  <pre><code>module Game where 
  import Player
  import Card 
  data Game = Game {p1 :: Player,
                    p2 :: Player,
                    isP1sTurn :: Bool
                    turnsLeft :: Int
                   }
  </code></pre>
  
  <p>a player module</p>
  
  <pre><code>module Player where
  import Card
  data Player = Player {score :: Int,
                        hand :: [Card],
                        deck :: [Card]
                       }
  </code></pre>
  
  <p>and a card module</p>
  
  <pre><code>module Card where
  data Card = Card {name :: String, scoreValue :: Int}
  </code></pre>
  
  <p>I then write some code to implement logic where players take turns drawing and playing cards from their hand to add bonuses to their score's until the game runs out of turns.</p>
  
  <p>However, I realize upon completion of this code that the game module I've written is boring!</p>
  
  <p>I want to refactor the card game so when you play a card, rather than just adding a score, instead the card arbitrarily transforms the game.</p>
  
  <p>So, I change the <code>Card</code> module to the following</p>
  
  <pre><code>module Card where
  import Game
  data Card = Card {name :: String, 
                    onPlayFunction :: (Game -&gt; Game)            
                    scoreValue :: Int}
  </code></pre>
  
  <p>which of course makes the module imports form a cycle.</p>
  
  <p>How do I resolve this problem?</p>
  
  <p>Trivial Solution:</p>
  
  <p>Move all the files to the same module. This solves the problem nicely, but reduces modularity; I can't later reuse the same card module for another game. </p>
  
  <p>Module maintaining solution:</p>
  
  <p>Add a type parameter to <code>Card</code>:</p>
  
  <pre><code>module Card where
  data Card a = {name :: String, onPlayFunc :: (a -&gt; a), scoreValue :: Int}
  </code></pre>
  
  <p>Add another parameter to <code>Player</code>:</p>
  
  <pre><code>module Player where
  data Player a {score :: Int, hand :: [card a], deck :: [card a]}
  </code></pre>
  
  <p>With one final modification to <code>Game</code>:</p>
  
  <pre><code>module Game where
  data Game = Game {p1 :: Player Game,
                    p2 :: Player Game,
                   }
  </code></pre>
  
  <p>This keeps modularity, but requires me to add parameters to my data types. If the data structures were any more deeply nested I could have to add -a lot- of parameters to my data, and if I had to use this method for multiple solutions, I could end up with an unwieldy number of type modifiers.</p>
  
  <p>So, are there any other useful solutions to resolving this refactor, or are these the only two options?</p>