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
的子类型。