Reputation: 3055
I understand the following is an example of upper bound type parameterization in scala, where T must be a subtype of Command.
def getSomeValue[T <: Command] = ...
However, Today I found the following implementation of type parameterization with multiple parameter types and as I'm a beginner in scala, I'm quite unable to understand what actually it does. Is this means T must be subtype of either Command, Foo or Bar?
def getSomeValue[T <: Command : Foo : Bar] = ...
Upvotes: 3
Views: 215
Reputation: 51271
The stand-alone colon, in a type parameter specification, is actually shorthand (syntactic sugar) for a longer, and rather complicated, parameter invocation.
Example: def f[N: Numeric](n: N) = ...
is really: def f[N](n: N)(implicit ev: Numeric[N]) = ...
Meaning that when f(x)
is invoked there has to be an implicit in scope that matches Numeric[x.type]
.
So, in your example code fragment: def getSomeValue[T <: Command : Foo : Bar] = ...
The compiler turns that into, roughly, the following:
def getSomeValue[T <: Command](implicit ev1: Foo[T], ev2: Bar[T]) = ...
We can demonstrate this by providing just enough skeletal code to actually make it compilable.
class Command {}
class Foo[F] {}
class Bar[B] {}
class Cmd extends Command
def getSomeValue[T <: Command : Foo : Bar](t: T) = t
getSomeValue(new Cmd)(new Foo[Cmd], new Bar[Cmd])
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// implicit parameters supplied explicitly
Upvotes: 3
Reputation: 149618
Is this means T must be subtype of either Command, Foo or Bar?
No, the upper bound is still required for T
. You now must also have an implicit instance of Foo[T]
and Bar[T]
in scope when this method is called. This is called Context Bounds, and it syntax sugar for:
def getSomeValue[T <: Command](implicit f: Foo[T], b: Bar[T])
If you're unaware of what implicit means, refer to the documentation for more.
Upvotes: 3