https://scalafiddle.io/sf/Z2NGo9y/0
Это возможное решение, но оно не оптимально, но вы можете исключить больше шаблонов, введя что-то вроде бесформенного / магнолийного / скалярного извлечения, чтобы получить реализации для fromString
реализаций.
Но на самом деле Validated
и Applicative
ваши друзья здесь
РЕДАКТИРОВАТЬ: В соответствии с просьбой код здесь
import cats._
import cats.implicits._
import cats.data.Validated._
import cats.data.ValidatedNel
import cats.data.NonEmptyList
sealed trait Tr[T]
case object Tr1 extends Tr[String]
case object Tr2 extends Tr[Int]
case object Tr3 extends Tr[Array[Byte]]
object Tr{
def fromString(s:String):ValidatedNel[Throwable, Tr[_]] = s match {
case "1" => Tr1.validNel
case "2" => Tr2.validNel
case "3" => Tr3.validNel
case _ => new RuntimeException(s"$s is not a valid Tr").invalidNel
}
}
sealed trait Trr[T]
case object Trr1 extends Trr[String]
case object Trr2 extends Trr[Int]
case object Trr3 extends Trr[Array[Byte]]
object Trr{
def fromString(s:String):ValidatedNel[Throwable, Trr[_]] = s match {
case "1" => Trr1.validNel
case "2" => Trr2.validNel
case "3" => Trr3.validNel
case _ => new RuntimeException(s"$s is not a valid Trr").invalidNel
}
}
trait Trrr[T, T1]
case object Trrr1 extends Trrr[String, Int]
case object Trrr2 extends Trrr[Int, String]
case object Trrr3 extends Trrr[Int, Int]
case object Trrr4 extends Trrr[String, String]
case object Trrr5 extends Trrr[String, Array[Byte]]
object Trrr{
def fromString(s:String):ValidatedNel[Throwable, Trrr[_, _]] = s match {
case "1" => Trrr1.validNel
case "2" => Trrr2.validNel
case "3" => Trrr3.validNel
case "4" => Trrr4.validNel
case "5" => Trrr5.validNel
case _ => new RuntimeException(s"$s is not a valid Trrr").invalidNel
}
}
def doUseful[T1, T2](tr:Tr[T1], trr:Trr[T2], trrr:Trrr[T1,T2]):String = "called"
def dispatch(s1:String, s2:String, s3:String):Either[Throwable, String] = (
Tr.fromString(s1),
Trr.fromString(s2),
Trrr.fromString(s3),
)
.tupled
.leftMap(
errs => new RuntimeException(
Foldable[NonEmptyList].intercalate(errs.map(_.getMessage),"\n")
)
)
.toEither
.flatMap {
case (a@Tr1, b@Trr2, c@Trrr1) => Right(doUseful(a,b,c))
case _ => Left(new RuntimeException("non mapped possibility"))
//note the line below won't compile because there's no valid combination of T1, T2 to call doUseful
//case (a@Tr1, b@Trr2, c@Trrr4) => doUseful(a,b,c)
}
println(dispatch("1", "2", "1"))
println(dispatch("1", "2", "15"))
println(dispatch("1", "20", "15"))