まずは以下をご覧ください
以下のようなcase classがあったときにAのコンパニオンのunapplyは、それぞれ存在するが、戻り値型が異なっており
case class A(x: Int, y: String)
という違いがあります。
この違いは、case classのapplyやunapplyを(明示的に)渡して型クラスのインスタンスを生成するようなライブラリその他(例えば各種jsonのライブラリ、slickの <>
でのマッピングなど)で、面倒なことになります。
- ライブラリ側が対応してくれればいいけれど、それもどうなるのかわからない
- Scala 3では
Tuple.fromProductTyped
でTupleには変換できるが、それの存在だけではだめで、もう少し工夫しないと、Scala 2とScala 3で完全なcross buildができない - 若干話が逸れるけれど、case classのコンパニオンに共通の親を継承させる(親だけ2と3で別にする) 作戦をやろうとしたら
java.lang.VerifyError: Bad type on operand stack
になってつらい https://github.com/lampepfl/dotty/issues/12557
というわけで もう少し工夫しないと、Scala 2とScala 3で完全なcross buildができない
を、Scala 2の場合のみshapelessに依存させて解決する案がこちらです。
Scala 2
import shapeless.ops.product.ToTuple object AsTuple { implicit class AsTupleOps[A](private val value: A) extends AnyVal { def asTuple[B](implicit toTuple: ToTuple.Aux[A, B]): B = toTuple.apply(value) } }
Scala 3
import scala.deriving.Mirror.ProductOf object AsTuple { extension [A <: Product](value: A) { def asTuple(using mirror: ProductOf[A]): mirror.MirroredElemTypes = Tuple.fromProductTyped(value) } }
本来依存ゼロにするにはshapeless使わないほうが良いと思いますが、誰か・・・。
あるいは、もっとすごく簡単というかシンプルな方法が発見されたら教えて下さい。 (もしくはScala 3かScala 2の本体で機能追加されたら、追記するかもしれませんが・・・)