Scala 如何编写匹配多个具有不同签名的案例类的类型约束

Scala 如何编写匹配多个具有不同签名的案例类的类型约束,scala,types,static-typing,Scala,Types,Static Typing,假设我有一些案例类共享一个特征: trait MyCaseClasses { def generic: String } case class C1(l: List[Int], generic: String) extends MyCaseClasses case class C2(s: String, generic: String) extends MyCaseClasses case class C3(a: Int, b: Int, generic: String) extends M

假设我有一些案例类共享一个特征:

trait MyCaseClasses {
  def generic: String
}
case class C1(l: List[Int], generic: String) extends MyCaseClasses
case class C2(s: String, generic: String) extends MyCaseClasses
case class C3(a: Int, b: Int, generic: String) extends MyCaseClasses
我要做的是创建一个函数,它将这些case类中的任何一个作为参数。比如:

def caseClassCurry[T <: MyCaseClasses](generic: String, cc: T): (args) => T = {
  (args) => cc(args, generic)
}
当然,这不是编译。这里有两个问题我不知道如何解决:

args很难指定。它必须表示任意类型的可变数量的参数。你会怎么做

当我写出这个的版本时,我得到cc.type不带参数。我假设这是因为cc只继承MyCaseClasses的特性,而MyCaseClasses是一个特性,不接受参数——类型系统不能推断继承该特性的类可能有参数。我需要有一些方法来表明cc实际上接受了参数,见问题1。我将如何做到这一点

最理想的情况是,我想更改trait MyCaseClasses,以表明扩展它的类将具有任意数量的任何类型的附加参数,但如何实现这一点也不清楚。

这是如何实现的:

scala> trait F[T]{ def generic: String }
// defined trait F
scala> case class C1(l: List[Int], generic: String) extends F[List[Int]]
// defined case class C1
scala> case class C2(s: String, generic: String) extends F[String]
// defined case class C2

scala> def caseClassCurry[T](generic: String, cc: (T, String) => F[T]): T => F[T] = cc(_, generic)
def caseClassCurry[T](generic: String, cc: (T, String) => F[T]): T => F[T]

scala> caseClassCurry("c1", C1.apply)(List(1, 2, 3))
val res2: F[List[Int]] = C1(List(1, 2, 3),c1)
**编辑** 很抱歉,在上述解决方案中遗漏了C3案例,我找到了另一个解决方案,但仅适用于dotty,即scala3.0。在scala2中使用shapeless可能会起作用:

scala> trait F { def generic: String }
// defined trait F

scala> case class C1(generic: String, list: List[Int]) extends F
// defined case class C1

scala> case class C2(generic: String, str: String) extends F
// defined case class C2

scala> case class C3(generic: String, a: Int, b: Long) extends F
// defined case class C3

scala> def curry[T <: Tuple, C <: F](generic: String, cc: String *: T => C): T => C = t => cc(generic *: t)
def curry[T <: Tuple, C <: F](generic: String, cc: String *: T => C): T => C

scala> curry("hello", C1.apply.tupled)(Tuple1(List()))
val res0: C1 = C1(hello,List())

scala> curry("hello", C2.apply.tupled)(Tuple1("world"))
val res1: C2 = C2(hello,world)

scala> curry("hello", C3.apply.tupled)((0, 1L))
val res2: C3 = C3(hello,0,1)

这极有可能实现,但并不一定容易。要做到这一点,您可能需要无形状。你为什么需要这个?直接调用构造函数不是更容易吗?我假设所有信息都是动态的,因此我只需编写一个简单的工厂方法,返回一个选项或其中一个。@LuisMiguelMejíaSuárez,如果您能找到一种干净的方法,使用option/other在N个case类上实现类似的功能,我会接受这个答案。@Logister您真正需要什么?哪些信息是静态的,哪些是动态的。动态参数的格式是什么?非常接近-我可以调整它,但它不适用于可变数量的初始参数,请参见我示例中的C3,对吗?我必须用它们自己的子案例类包装多个参数案例。例如:案例类别C3arga:Int,b:Int;案例类C3arg:C3arg,generic:String扩展了F[C3arg]@Logister我已经更新了关于C3案例的答案。