Error: polymorphic expression with default arguments

These are the following errors of me:

trait Foo[A] class Bar[A](set: Set[Foo[A]] = Set.empty) 

This gives

 <console>:8: error: polymorphic expression cannot be instantiated to expected type; found : [A]scala.collection.immutable.Set[A] required: Set[Foo[?]] class Bar[A](set: Set[Foo[A]] = Set.empty) ^ 

It is very unpleasant that I have to repeat the type parameter in Set.empty . Why does a type query fail with this default argument? The following works:

 class Bar[A](set: Set[Foo[A]] = { Set.empty: Set[Foo[A]] }) 

Note that this has nothing to do with Set in particular:

 case class Hallo[A]() class Bar[A](hallo: Hallo[A] = Hallo.apply) // nope 

Strange not only does this work:

 class Bar[A](hallo: Hallo[A] = Hallo.apply[A]) 

... but also this:

 class Bar[A](hallo: Hallo[A] = Hallo()) // ??? 
+8
scala type-inference default-value
source share
1 answer

You can specify the type directly using the empty method, rather than adding an additional set of characters / curly braces and type annotation:

 class Bar[A]( set: Set[Foo[A]] = Set.empty[Foo[A]] ) 

Regarding the output of type inference, see the following questions:

  • Type inference when installation fails
  • Missing parameter type error by calling toSet

Update:

I apologize, my hasty answer is gone. The problem in the above posts is really not related to this problem. @TravisBrown made a very good point in his comment above. This works first:

 class Bar[A]( set: Set[A] = Set.empty ) 

But if you are actually trying to call the constructor, it does not work on the use site:

 new Bar[Int] // <console>:9: error: type mismatch; // found : scala.collection.immutable.Set[Nothing] // required: Set[Int] // Note: Nothing <: Int, but trait Set is invariant in type A. // You may wish to investigate a wildcard type such as `_ <: Int`. (SLS 3.2.10) // Error occurred in an application involving default arguments. // new Bar[Int] 

This suggests that the compiler does not force the default parameter to be valid for all A , only for some A They probably made the choice to do something like this:

 scala> case class MyClass[T](set: Set[T] = Set(0)) defined class MyClass scala> MyClass() // defaults to MyClass[Int] res0: MyClass[Int] = MyClass(Set(0)) scala> MyClass(Set('x)) // but I can still use other types manually res1: MyClass[Symbol] = MyClass(Set('x)) 

However, any type of attachment with a parameterized type cannot enter a check on the announcement site in the constructor:

 class Bar[A]( set: Set[Option[A]] = Set.empty ) // <console>:7: error: polymorphic expression cannot be instantiated to expected type; // found : [A]scala.collection.immutable.Set[A] // required: Set[Option[?]] // class Bar[A]( set: Set[Option[A]] = Set.empty ) 

The output is not interrupted if the type parameter is in the covariant position:

 class Bar[ A ]( set: List[Foo[A]] = List.empty ) // OK class Bar[ A ]( set: Map[Int,Foo[A]] = Map.empty ) // OK (unless you use it) class Bar[ A ]( set: Map[Foo[A],Int] = Map.empty ) // BAD // <console>:8: error: polymorphic expression cannot be instantiated to expected type; // found : [A, B]scala.collection.immutable.Map[A,B] // required: Map[Foo[?],Int] // class Bar[ A ]( set: Map[Foo[A],Int] = Map.empty ) // BAD // ^ 

They work because by default the compiler selects Nothing as a covariant type. This works fine for List , but the second example above does not work if you are actually trying to call it.

The reason for most of this oddity is probably the way Scala handles default arguments. The compiler automatically adds an additional method to the companion object, and then, wherever you leave the argument, the compiler automatically adds a method call to the new method in the companion object to generate the missing argument instead. It seems that abstracting the default argument to the method violates some things in the output type that will work with the usual purpose.

I think most of these finds are quite confusing. What I take away from this is that it is important to check your default settings to make sure that they do not violate the correct type when you try to use them!

+5
source share

All Articles