Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Scala infer the type parameter in this example?

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?

like image 533
Jay Conrod Avatar asked Jul 26 '09 19:07

Jay Conrod


People also ask

Does Scala support type inference?

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.

What would be the type inferred by Scala compiler for variable?

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.

What is type parameter in Scala?

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.

What is infer generic type arguments?

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.


1 Answers

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.

like image 55
psp Avatar answered Sep 20 '22 23:09

psp