title: Advice defining a data structure in Haskell
body: <p>I'm having trouble modeling a data structure in Haskell. Suppose I'm
  running an an animal research facility and I want to keep track of my
  rats. I want to track the assignment of the rats to cages and to
  experiments. I also want to keep track of the weight of my rats, the
  volume of my cages, and keep notes on my experiments.</p>
  
  <p>In SQL, I might do:</p>
  
  <pre><code>create table cages (id integer primary key, volume double);
  create table experiments (id integer primary key, notes text)
  create table rats (
      weight double,
      cage_id integer references cages (id),
      experiment_id integer references experiments (id)
  );
  </code></pre>
  
  <p>(I realize that this allows me to assign two rats from different
  experiments to the same cage. That is intended. I don't actually run an
  animal research facility.)</p>
  
  <p>Two operations that must be possible: (1) given a rat, find the volume of its cage and (2) given a rat, get the notes for the experiment it belongs to.</p>
  
  <p>In SQL, those would be</p>
  
  <pre><code>select cages.volume from rats
    inner join cages on cages.id = rats.cage_id
    where rats.id = ...; -- (1)
  select experiments.notes from rats
    inner join experiments on experiments.id = rats.experiment_id
    where rats.id = ...; -- (2)
  </code></pre>
  
  <p>How might I model this data structure in Haskell?</p>
  
  <hr>
  
  <p>One way to do it is</p>
  
  <pre><code>type Weight = Double
  type Volume = Double
  
  data Rat = Rat Cage Experiment Weight
  data Cage = Cage Volume
  data Experiment = Experiment String
  
  data ResearchFacility = ResearchFacility [Rat]
  
  ratCageVolume :: Rat -&gt; Volume
  ratCageVolume (Rat (Cage volume) _ _) = volume
  
  ratExperimentNotes :: Rat -&gt; String
  ratExperimentNotes (Rat _ (Experiment notes) _) = notes
  </code></pre>
  
  <p>But wouldn't this structure introduce a bunch of copies of the <code>Cage</code>s and <code>Experiment</code>s? Or should I just not worry about it and hope the optimizer takes care of that?</p>