title: Defining allowed value ranges in type member in F#
body: <p>I'm playing around with <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/units-of-measure" rel="nofollow noreferrer">units of measure</a> in F# and I'm currently trying to create compound units of measure for length and mass to reflect colloquial speech in the imperial system, e.g. &quot;I'm 5 foot 10&quot; or &quot;She weighs 8 stone and 11 pounds&quot; in the US and the UK.</p>
  <p>I've defined a module for standard (non-compound) units like so:</p>
  <pre class="lang-ml prettyprint-override"><code>module Units
      // Mass
      [&lt;Measure&gt;] type kg // Kilogram
      [&lt;Measure&gt;] type g  // Gram
      [&lt;Measure&gt;] type lb // Pound (mass)
      [&lt;Measure&gt;] type st // Stone (mass)
      
      // Conversions
      ...
  
      // Length
      [&lt;Measure&gt;] type m      // Metre
      [&lt;Measure&gt;] type cm     // Centimetre
      [&lt;Measure&gt;] type inch   // Inch
      [&lt;Measure&gt;] type ft     // Foot
  
      // Conversions
      ...
  </code></pre>
  <p>And I've defined compound units in a different module:</p>
  <pre class="lang-ml prettyprint-override"><code>module CompoundUnits
      open Units
      
      // Mass
      type StonesAndPounds = {
          Stones: float&lt;st&gt;
          Pounds: float&lt;lb&gt;
      }
  
      // Length
      type FeetAndInches = {
          Feet: float&lt;ft&gt;
          Inches: float&lt;inch&gt;
      }
  </code></pre>
  <p>However, with the way I've currently written the compound mass and length types, there's room for illegal states (such as negative values) and states that are <em>technically correct</em> but not preferred:</p>
  <pre class="lang-ml prettyprint-override"><code>// 39 lbs = 2 st 11 lbs
  let eightStoneEleven: StonesAndPounds = { Stones = 6.0&lt;st&gt;; Pounds = 39.0&lt;lb&gt; }
  // 22&quot; = 1' 10&quot;
  let fiveFootTen: FeetAndInches = { Feet = 4.0&lt;ft&gt;; Inches = 22.0&lt;inch&gt; }
  </code></pre>
  <p>In his book &quot;Domain Modeling made Functional&quot; Scott Wlaschin talks about making illegal states unrepresentable, so I was wondering if there was a way to enforce some kind of restriction on my compound types so that <code>0&lt;ft&gt; &lt;= Feet</code>, <code>0&lt;inch&gt; &lt;= Inches &lt;= 12&lt;inch&gt;</code> and <code>0&lt;st&gt; &lt;= Stones</code>, <code>0&lt;lb&gt; &lt;= Pounds &lt;= 14&lt;lb&gt;</code>.</p>