К сожалению, для этого вам необходимо использовать HLists. Вот пример с бесформенным 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
(я предполагаю, что это является requriement.
def func: Args => O
Функция, которая принимает HList из " форма»Args
и возвращает O
. (вы также можете написать это как метод, если вы предпочитаете.
case class Predicate1 /*snip*/ extends Preciate[I1 :: HNil, O]
Predicate1
- это Predicate
, список аргументов которого содержит один элемент типа I1
.
implicit val lubWitness = implicitly[LUBConstraint[I1 :: HNil, Arg]]
Получить и определить свидетельство, что I1
подтипом Arg
(что имеет место, в связи с типом связанного в декларации Predicate1
.
спасибо, это Shaeless 2? – Omid
Должен работать и с более старыми версиями Shapeless. – gzm0
Вы могли бы предоставить экземпляр Predicate1? Я не могу давать аргументы как Hlist – Omid