How could I have something like
var tuple : (Option[Any]) | (Option[Any], Option[Any]) | (Option[Any], Option[Any], Option[Any]) | (Option[Any], Option[Any], Option[Any], Option[Any])
But more elegantly?
CodePudding user response:
Scala 3 unions are flashy and fun, but there's something to be said for slightly more traditional methods, especially when you end up with a type signature that requires a horizontal scrollbar.
In this case, since your priority seems to be type safety on the individual tuple elements, I might suggest a sealed trait
with case class
es for children.
sealed trait MySpecialTuple
case class MyOneTuple(
val field: Option[Any],
) extends MySpecialTuple
case class MyTwoTuple(
val leftHandSide: Option[Int],
val rightHandSide: Option[String],
) extends MySpecialTuple
...
var tuple: MySpecialTuple
Since it's sealed
, you can exhaustively pattern match against it to figure out what's inside. If you want to add additional functionality (like a way to get the "length" of the thing or some other property), that can be a method on MySpecialTuple
. The point, here, is to offload the incredible complexity of "this thing can be one of ten different shapes" onto a bunch of named, well-documented classes rather than hiding it away in a one-liner variable declaration.
CodePudding user response:
You can do something like this in scala3.0:
scala> type OptTuple[T <: Tuple] = T match
| case Option[_] *: t => OptTuple[t]
| case EmptyTuple => DummyImplicit
|
scala> case class MyTuple[T <: Tuple : OptTuple](tuple: T)
// defined case class MyTuple
scala> val t1 = MyTuple((Option(1), Option("a"), Option(3.0)))
val t1: MyTuple[(Option[Int], Option[String], Option[Double])] = MyTuple((Some(1),Some(a),Some(3.0)))
scala> val t2 = MyTuple((Option(1), Option("a"), 3.0))
-- Error: ----------------------------------------------------------------------
1 |val t2 = MyTuple((Option(1), Option("a"), 3.0))
| ^
| Match type reduction failed since selector Double *: EmptyTuple.type
| matches none of the cases
|
| case Option[_] *: t => OptTuple[t]
| case EmptyTuple => DummyImplicit
1 error found