Make42
Make42

Reputation: 13088

How to pass (different) generics to varags?

I have a container class

object OptimisationVariable {

  implicit class OptimisationVariableSeq[B](seq: Seq[OptimisationVariable[B]]) {
    def extract[A: ClassTag](variable: (OptimisationVariable[B] => A)): DenseVector[A] =
      DenseVector(seq.map(variable).toArray)
  }

}

final case class OptimisationVariable[B: ClassTag](startposition: B,       
                                                   startlearningrate: Double)

which I want to pass to my algorithm:

class MyAlgorithm(optimisationVariable: OptimisationVariable*)

but I get the error that OptimisationVariable takes a type parameters. That makes sense. However I want to pass be able to pass different kinds of parameter. Since optimisationVariable is going to be a Seq, I am not sure how I am supposed to go about this. B is going to be an Int or a Double. E.g.

new MyAlgorithm(OptimisationVariable(1, 2.0), OptimisationVariable(3.0, 4.0))

Later I want to decide what to do, depending on whether its an Int or a Double.

Upvotes: 0

Views: 151

Answers (2)

I See Voices
I See Voices

Reputation: 842

I simplified your example a bit, so as I understood, essentially you want this:

case class Ov[A](start: A, degree: Double)
case class MyAlg[L <: HList : *->*[Ov]#λ](ov: L)

MyAlg(Ov(1, 2):: Ov("Hello", 2) :: HNil) //compiles
MyAlg(1 :: HNil)     // won't compile

Now you can pass any number of OptimizedVariables, keeping their type. Then if you need to map over it, you just define polymorphic function (from shapeless) for the types you are gonna use.

Actually, if they are only Int or Double, you can do

case class Ov1(start: Int \/ Double, degree: Double) // \/ from scalaZ
case class MyAlg1(ov: List[Ov1])

or even use union types from shapeless (|v|) instead of \/

Upvotes: 0

tkroman
tkroman

Reputation: 4798

If you are not going to restrict B at all, using existential type is OK:

final case class OptimisationVariable[B: ClassTag](
    startposition: B,
    startlearningrate: Double
)
case class MyAlgorithm(optimisationVariable: OptimisationVariable[_]*)
// and then
MyAlgorithm(OptimisationVariable(1, 1.0), OptimisationVariable(2, 1.1))

If you are going to restrict them by some upper bound, throw in some typeclasses and you are still good.

In case you are inspired to try shapeless, as suggested by the comments above, here's a good starting book (Fret not! It's short and practical): shapeless-guide

Upvotes: 1

Related Questions