title: Scala type constraint to check argument values
body: <p>I'm trying to implement Conway's <a href="https://en.wikipedia.org/wiki/Surreal_number#Construction" rel="noreferrer">surreal numbers</a> in Scala. A surreal number is defined recursively – as a pair of sets of surreal numbers, called left and right, such that no element in the right set is less than or equal to any element in the left set. Here the relation &quot;less than or equal to&quot; between surreal numbers is also defined recursively: we say that <em>x</em> ≤ <em>y</em> if</p>
  <ul>
  <li>there is no element <em>a</em> in the left set of <em>x</em> such that <em>y</em> ≤ <em>a</em>, and</li>
  <li>there is no element <em>b</em> in the right set of <em>y</em> such that <em>b</em> ≤ <em>x</em>.</li>
  </ul>
  <p>We start with defining zero as a pair of empty sets, then use zero to define 1 and -1, and so on.</p>
  <p>I cannot figure out how to enforce the definition of a surreal number at compile time. This is what I have now:</p>
  <pre class="lang-scala prettyprint-override"><code>case class SurrealNumber(left: Set[SurrealNumber], right: Set[SurrealNumber]) {
    if ((for { a &lt;- left; b &lt;- right; if b &lt;= a } yield (a, b)).nonEmpty)
      throw new Exception
    def &lt;=(other: SurrealNumber): Boolean =
      !this.left.exists(other &lt;= _) &amp;&amp; !other.right.exists(_ &lt;= this)
  }
  
  val zero = SurrealNumber(Set.empty, Set.empty)
  val one = SurrealNumber(Set(zero), Set.empty)
  val minusOne = SurrealNumber(Set.empty, Set(zero))
  
  assert(zero &lt;= zero)
  assert((zero &lt;= one) &amp;&amp; !(one &lt;= zero))
  assert((minusOne &lt;= zero) &amp;&amp; !(zero &lt;= minusOne))
  </code></pre>
  <p>When the arguments are invalid, as in <code>SurrealNumber(Set(one), Set(zero))</code>, this code would throw a runtime exception. Is it possible to express the validity check as a type constraint, so that <code>SurrealNumber(Set(one), Set(zero))</code> wouldn't compile?</p>