Suppose I have two classes, Input
and Output
, which are designed to be connected to each other. Output
produces values of some type, and Input
consumes them.
class Input[T] {
var output: Option[Output[_ <: T]] = None
}
class Output[T] {
var input: Option[Input[_ >: T]] = None
}
It's okay if an Input
and Output
pair don't operate on the same kind of value as long as the Input
type parameter is a supertype of the Output
type parameter. Note that the type parameter in both classes is invariant; in the real versions it is used in both co- and contravariant positions.
I have a connect
method elsewhere which sets up a link between an Input
/Output
pair:
def connect[T](output: Output[T], input: Input[_ >: T]) = {
output.input = Some(input)
input.output = Some(output)
}
If I call this method as below, I get a type error:
val out = new Output[String]
val in = new Input[AnyRef]
connect(out, in)
The error is:
test.scala:17: error: type mismatch;
found : Output[String]
required: Output[AnyRef]
connect(out, in)
^
I can resolve this by writing out the type parameter (in this case, I would write connect[String]
, but I think the compiler should be able to figure this out for me. How can I change the connect
method so that the type parameter is inferred automatically?
Edit: For now, I've made connect
a method of Output
so it gets the type parameter automatically. This also has the added benefit that I can use the infix notation out connect in
, but the design feels a little awkward.
I am still interested in why the compiler exhibits this behavior. I feel like it should be able to infer the type parameter. Is this actually working as specified?
The Scala compiler can infer the types of expressions automatically from contextual information. Therefore, we need not declare the types explicitly. This feature is commonly referred to as type inference. It helps reduce the verbosity of our code, making it more concise and readable.
Scala compiler can automatically infer types of each variable declared. If the value of a variable is declared in double-quotes it will automatically be inferred as String. Also, the compiler can infer any value in a single quote is inferred as Char. The compiler, by default it infer any number without decimal as Int.
Language. Methods in Scala can be parameterized by type as well as by value. The syntax is similar to that of generic classes. Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses.
Type inference represents the Java compiler's ability to look at a method invocation and its corresponding declaration to check and determine the type argument(s). The inference algorithm checks the types of the arguments and, if available, assigned type is returned.
You will sometimes get better results if you use multiple parameter lists:
def connect[T](output: Output[T])(input: Input[_ >: T]) = {
output.input = Some(input)
input.output = Some(output)
}
connect(out)(in)
...and indeed in this case, it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With