Luc Ebert
Luc Ebert

Reputation: 1255

Scala Upper type bounds implicitly?

I have a first trait like this :

trait FirstTrait[U] {
  val myVal: U
}

And another one as follows :

trait SecondTrait[T <: firstTrait[U],U]

For the implementation I am doing :

case class FirstImpl(myVal: MyType) extends FirstTrait[MyType]

object SecondImpl extends SecondTrait[FirstImpl,MyType]

Is there a better way to do the same thing, I would like to simplify my implementation of the second trait like this if possible :

object SecondImpl extends SecondTrait[FirstImpl]

EDIT

I am using after both type in a function :

  def func[T <: FirstTrait[U],U](myVal: T): U

When I use existential type, I have to explicit types or I get an "inferred type arguments [FirstImpl,Nothing] do not conform to method func" error.

So this is how I have to implement the function :

val myVal : MyType = MyType()
func[FirstImpl,MyType](FirstImpl(myVal))

Can anything simplify?

Upvotes: 1

Views: 154

Answers (2)

Dmytro Mitin
Dmytro Mitin

Reputation: 51648

You can try existential type

trait FirstTrait[U] {
  type _U = U
  val myVal: U
}

trait SecondTrait[T <: FirstTrait[_]]

case class FirstImpl(myVal: MyType) extends FirstTrait[MyType]

object SecondImpl extends SecondTrait[FirstImpl]

def func[T <: FirstTrait[_]](myVal: T): myVal._U = ???

func(FirstImpl(myVal)): MyType

or

trait FirstTrait {
  type U
  val myVal: U
}

trait SecondTrait[T <: FirstTrait]

case class FirstImpl(myVal: MyType) extends FirstTrait { type U = MyType }

object SecondImpl extends SecondTrait[FirstImpl]

def func[T <: FirstTrait](myVal: T): myVal.U = ???

func(FirstImpl(myVal)): MyType

or

def func[T, U](myVal: T)(implicit ev: T <:< FirstTrait[U]): U = ???

Upvotes: 3

Alexey Romanov
Alexey Romanov

Reputation: 170713

def func[T <: FirstTrait[U],U](myVal: T): U    

The problem is that the type of myVal doesn't mention U, so the compiler is failing to infer it simultaneously with T. If it inferred T first, it could get U from it, but it doesn't currently work this way.

However, T is actually useless here and it can be rewritten as

def func[U](myVal: FirstTrait[U]): U    

You can already pass any subtype of FirstTrait[U] here and lose the source of the type inference problem.

If this is a simplified signature, a trick which can work is mentioning U in the parameter type even if it should be redundant:

def func[T <: FirstTrait[U], U](myVal: T with FirstTrait[U]): U    

Upvotes: 2

Related Questions