Scala “如何制作表单的方法”;将(s:s,i:i):s与i组合;通用的

Scala “如何制作表单的方法”;将(s:s,i:i):s与i组合;通用的,scala,types,Scala,Types,鉴于此代码: trait S { def s: String } trait I { def i: Int } case class CC_S(s: String) extends S case class CC_I(i: Int) extends I case class CC_S_I(s: String, i: Int) extends S with I def combine(s: S, i: I): S with I = CC_S_I

鉴于此代码:

  trait S {
    def s: String
  }

  trait I {
    def i: Int
  }

  case class CC_S(s: String) extends S
  case class CC_I(i: Int) extends I
  case class CC_S_I(s: String, i: Int) extends S with I

  def combine(s: S, i: I): S with I = CC_S_I(s.s, i.i)
此测试成功:

Assert.assertEquals(CC_S_I("s", 1), combine(CC_S("s"), CC_I(1)))
(如何)将combine方法作为带有类型参数的特征进行泛型?也就是说,我想定义如下:

  trait MyTrait[A,B] {
    def combine(a: A, b: B): A with B
  }
  class MyClass[A <: CC_S, B <: CC_I] extends MyTrait[A,B] {
    override def combine(s: A, i: B) = CC_S_I(s.s, i.i) //Note: this line does not compile...
  }

  Assert.assertEquals(CC_S_I("s", 1), new MyClass().combine(CC_S("s"), CC_I(1)))
所以我可以这样使用它:

  trait MyTrait[A,B] {
    def combine(a: A, b: B): A with B
  }
  class MyClass[A <: CC_S, B <: CC_I] extends MyTrait[A,B] {
    override def combine(s: A, i: B) = CC_S_I(s.s, i.i) //Note: this line does not compile...
  }

  Assert.assertEquals(CC_S_I("s", 1), new MyClass().combine(CC_S("s"), CC_I(1)))

class MyClass[A问题在于
CC\u S\u I
实际上不是
CC\u S
CC\u I
的子类型(尽管它是
S
I
的子类型)。以下操作将起作用:

class MyClass extends MyTrait[S, I] {
  def combine(s: S, i: I): S with I = CC_S_I(s.s, i.i)
}

作为补充说明,如果您正在进行大量此类工作,则该库值得研究。它允许您非常通用地编写
combine
方法:

import shapeless._

def combine[A, B, C, AL <: HList, BL <: HList, CL <: HList](a: A, b: B)(implicit
  aIso: Iso[A, AL],
  bIso: Iso[B, BL],
  cIso: Iso[C, CL],
  p: PrependAux[AL, BL, CL]
): C = cIso from p(aIso to a, bIso to b)
你可以写:

scala> val x = combine[
     |   CC_S, CC_I, CC_S_I, String :: HNil, Int :: HNil, String :: Int :: HNil
     | ](CC_S("s"), CC_I(1))
x: CC_S_I = CC_S_I(s,1)

不幸的是,这个公式需要大量的类型注释,但这应该会让您了解可能的情况,并且您可以做一些事情来让用法更简洁。

谢谢!这比我想象的要简单。不过我也尝试过这个(这是一个更好的示例):
MyClass[A事实上是一样的,如果
A
B
分别是
S
I
的任意子类型,你不能保证
CC\U U I
将是
A和B
的子类型。