抽象函数的可变参数个数

时间:2015-04-16 20:02:35

标签: scala

我有以下代码:

trait TypeLike
trait ArgLike
trait Predicate{
  def name:String

}

case class Arg(name:String)

case class Predicate1[I1<:Arg,O<:TypeLike](name:String, arg1:I1, output:O, func: I1=> O) extends Predicate


case class Predicate2[I1<:Arg,I2<:Arg,O<:TypeLike](name:String, arg1:I1,arg2:I2, output:O, func: (I1,I2)=> O)
  extends Predicate

如何在谓词特征中添加&#34; func&#34; 。我不知道如何用可变数量的输入来定义抽象函数。

2 个答案:

答案 0 :(得分:1)

不幸的是,您必须使用HLists。以下是Shapeless HLists的示例:

import shapeless._

trait Predicate[Args <: HList, O <: TypeLike] {
  implicit val lubWitness: LUBConstraint[Args, Arg]
  def name: String
  def func: Args => O
}

case class Predicate1[I1 <: Arg, O <: TypeLike](
    name: String,
    arg1: I1,
    output: O,
    func: I1 :: HNil => O
) extends Predicate[I1 :: HNil, O] {
    implicit val lubWitness = implicitly[LUBConstraint[I1 :: HNil, Arg]]
}

case class Predicate2[I1 <: Arg, I2 <: Arg, O <: TypeLike](
    name: String,
    arg1: I1,
    arg2: I2,
    output: O,
    func: I1 :: I2 :: HNil => O
) extends Predicate[I1 :: I2 :: HNil, O] {
    implicit val lubWitness = implicitly[LUBConstraint[I1 :: I2 :: HNil, Arg]]
}

// Example instantiation
val p1 = Predicate1("Example", Arg("test"), new TypeLike {},
  (args: Arg :: HNil) => { println(args(0)); ??? })

<强>解释

那么这里发生了什么? HList基本上是立体声的元组。让我们来看看我们的例子:

trait Predicate[Args <: HList, O <: TypeLike] {

Args <: HList表示Args是一个类型列表。 O <: TypeLike是带有绑定的普通类型参数。

implicit val lubWitness: LUBConstraint[Args, Arg]

这说明我们需要证明HList Args中的每个类型都是Arg的子类型(我假设这是一个要求。

def func: Args => O

采用&#34;形状&#34;的HList的函数。 Args并返回O。 (如果您愿意,也可以将其写为方法。

case class Predicate1 /*snip*/ extends Preciate[I1 :: HNil, O]

Predicate1Predicate,其参数列表包含一个I1类型的元素。

implicit val lubWitness = implicitly[LUBConstraint[I1 :: HNil, Arg]]

检索并定义I1Arg的子类型的见证(由于Predicate1声明中的类型绑定,情况就属于这种情况。

答案 1 :(得分:-2)

作为类型参数的元组可以模拟类似于您的问题的东西。这种方法有两个局限。你应该在func调用上使用额外的parens,而元组对22项计数有限制。

trait TypeLike
trait ArgLike
trait Predicate[X, O] {

  def name:String

  def func(f: X): O
}

case class Arg(name:String)

case class Predicate1[I1<:Arg,O<:TypeLike, X <: Tuple1[I1]](name:String, arg1:I1, output:O) extends Predicate[X, O] {
  override def func(f: X): O = ???
}


case class Predicate2[I1<:Arg,I2<:Arg,O<:TypeLike, X <: Tuple2[I1, I2]](name:String, arg1:I1,arg2:I2, output:O)
  extends Predicate[X, O] {
  override def func(f: X): O = ???
}