Three-way encoding, inclusive - or type Scala

I have some data that consists of three fields, say a String, a Intand a Double.

All of them are optional, but all this should contain at least one of these fields.

I tried cats.data.Iorfor example type MyType = String Ior Int Ior Double. He works, but he feels a little awkward when he actually does things with him. Creating case classwith three Optionand throwing exceptions in the constructor if they all Noneshould work too, but I don't like this idea.

I am curious to find out if there can be some other way to do this (preferably encoding all the information only in type types Ior, but with less complexity, so using type values ​​is not that difficult). Suggestions for using any other libraries are also welcome.

+4
source share
1 answer

You probably also thought about this idea, but what about this:

class StringOrIntOrDouble private(val first: Option[String], val second: Option[Int], val third: Option[Double]) {
  def this(first: String) = this(Some(first), None, None)

  def this(second: Int) = this(None, Some(second), None)

  def this(third: Double) = this(None, None, Some(third))

  def this(first: String, second: Int) = this(Some(first), Some(second), None)

  def this(second: Int, third: Double) = this(None, Some(second), Some(third))

  def this(first: String, third: Double) = this(Some(first), None, Some(third))

  def this(first: String, second: Int, third: Double) = this(Some(first), Some(second), Some(third))

}

The main constructor private, so you cannot create an empty instance. Obviously, you could expand it with the implementation of Product, and equals, hashCode, toStringand other useful things as classes case (but beware copythat can easily break the invariant).

, , ( ), "" - - .

class TripleIor[+A, +B, +C] private(val first: Option[A], val second: Option[B], val third: Option[C]) {

}

object TripleIor {
  def first[A](first: A) = new TripleIor[A, Nothing, Nothing](Some(first), None, None)

  def second[B](second: B) = new TripleIor[Nothing, B, Nothing](None, Some(second), None)

  def third[C](third: C) = new TripleIor[Nothing, Nothing, C](None, None, Some(third))

  def firstAndSecond[A, B](first: A, second: B) = new TripleIor[A, B, Nothing](Some(first), Some(second), None)

  def secondAndThird[B, C](second: B, third: C) = new TripleIor[Nothing, B, C](None, Some(second), Some(third))

  def firstAndThird[A, C](first: A, third: C) = new TripleIor[A, Nothing, C](Some(first), None, Some(third))

  def apply[A, B, C](first: A, second: B, third: C) = new TripleIor[A, B, C](Some(first), Some(second), Some(third))
}

, sealed trait 7 , , . , copy , ( ).

sealed trait TripleIor[A, B, C] extends Product {
  def firstOption: Option[A]

  def secondOption: Option[B]

  def thirdOption: Option[C]
}

object TripleIor {

  final case class First[A](first: A) extends TripleIor[A, Nothing, Nothing] {
    override def firstOption: Option[A] = Some(first)

    override def secondOption: Option[Nothing] = None

    override def thirdOption: Option[Nothing] = None
  }

  final case class Second[B](second: B) extends TripleIor[Nothing, B, Nothing] {
    override def firstOption: Option[Nothing] = None

    override def secondOption: Option[B] = Some(second)

    override def thirdOption: Option[Nothing] = None
  }

  final case class Third[C](third: C) extends TripleIor[Nothing, Nothing, C] {
    override def firstOption: Option[Nothing] = None

    override def secondOption: Option[Nothing] = None

    override def thirdOption: Option[C] = Some(third)
  }

  final case class FirstSecond[A, B](first: A, second: B) extends TripleIor[A, B, Nothing] {
    override def firstOption: Option[A] = Some(first)

    override def secondOption: Option[B] = Some(second)

    override def thirdOption: Option[Nothing] = None
  }

  final case class SecondThird[B, C](second: B, third: C) extends TripleIor[Nothing, B, C] {
    override def firstOption: Option[Nothing] = None

    override def secondOption: Option[B] = Some(second)

    override def thirdOption: Option[C] = Some(third)
  }

  final case class FirstThird[A, C](first: A, third: C) extends TripleIor[A, Nothing, C] {
    override def firstOption: Option[A] = Some(first)

    override def secondOption: Option[Nothing] = None

    override def thirdOption: Option[C] = Some(third)
  }

  final case class All[A, B, C](first: A, second: B, third: C) extends TripleIor[A, B, C] {
    override def firstOption: Option[A] = Some(first)

    override def secondOption: Option[B] = Some(second)

    override def thirdOption: Option[C] = Some(third)
  }
}

P.S. , - , , .

+1

Source: https://habr.com/ru/post/1690222/


All Articles