Class accepting only distinct order couple of Int

How in Scala3 to create a case class of objects accepting only a distinct ordered (Int, Int) couple? That is the first Int is always smaller than the second.

import scala.util.Try

case class OrderedDistinctPair(v1: Int, v2: Int):

  require(isOrdered)

  def isOrdered: Boolean = v1 < v2

object OrderedDistinctPair:
  def maybeCreate(v1: Int, v2: Int): Try[OrderedDistinctPair] = Try {
    if (v1 > v2) OrderedDistinctPair(v2, v1) else OrderedDistinctPair(v1, v2)
  }

I came up with this, providing a companion method if you don’t want to care about providing the correct order.

But I have a feeling there might much better approaches…

Any suggestion? Thank you in advance.

Mhh. Why a Try here ? Actually, you’re not throwing any exception and you’re handling all cases.

OrderedDistinctPair(3, 3) fails, is not distinct

In this case, I suggest you to use an Option instead.

case class OrderedDistinctPair(v1: Int, v2: Int)

object OrderedDistinctPair:
  def maybe(v1: Int, v2: Int): Option[OrderedDistinctPair] =
    if v1 > v2 then Some(OrderedDistinctPair(v1, v2))
    else if v1 < v2 then Some(OrderedDistinctPair(v2, v1))
    else None

If you have multiple failure case (here, we only have x == y), you can use an Either[YourException, OrderedDistinctPair] instead of an Option.

1 Like

Don’t forget to make constructor/apply private.

case class OrderedDistinctPair private(lo: Int, hi: Int)
1 Like

Ok, thank you all for the suggestions.

The bit from @sangamon I think replies to the question I now had in mind: how to avoid that an invalid OrderedDistinctPair is created with the standard constructor. Otherwise I was needing require to be sure that something like OrderedDistinctPair(4, 2) cannot happen.

Forgot to note that in Scala 3 this makes #copy() private, as well.