È possibile specificare il tipo direttamente sul metodo empty
piuttosto che dover aggiungere il set supplementare di parentesi/bretelle e il tipo di annotazione:
class Bar[A](set: Set[Foo[A]] = Set.empty[Foo[A]])
Per quanto riguarda il motivo per cui l'inferenza di tipo non riesce, vedi queste domande :
Aggiornamento:
Mi scuso, la mia risposta frettolosa era fuori strada. Il problema nei post precedenti non è realmente correlato a questo problema. @TravisBrown ha fatto un ottimo punto nel suo commento sopra. Questo sembra funzionare in un primo momento:
class Bar[A](set: Set[A] = Set.empty)
Ma se in realtà tenta di chiamare il costruttore non riesce a uso loco:
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]
Ciò suggerisce che il compilatore non forzare il parametro di default per essere valido per tutti A
, solo per alcuni A
. Probabilmente fatto questa scelta in modo da poter fare qualcosa di simile:
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))
Tuttavia, qualsiasi tipo di nidificazione con il tipo di parametri non riesce a digitare verificare presso il sito di dichiarazione nel costruttore:
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)
Il inferenza non sicuro se il parametro tipo è in una posizione covariante:
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
// ^
Questi funzionano perché il compilatore seleziona Nothing
come co tipo di variante per impostazione predefinita.Funziona bene per List
, ma il secondo esempio sopra non funziona se si tenta effettivamente di chiamarlo.
La causa della maggior parte di questa stranezza è probabilmente il modo in cui Scala gestisce gli argomenti predefiniti. Il compilatore aggiunge automaticamente un metodo extra all'oggetto complementare, e quindi ovunque si ometta un argomento il compilatore aggiunge automaticamente una chiamata al nuovo metodo nell'oggetto complementare per generare invece l'argomento mancante. Sembra che l'astrazione dell'argomento predefinito in un metodo rompa alcune cose nell'inferenza di tipo che funzionerebbe con un normale compito.
Penso che molte di queste scoperte siano piuttosto confuse. Ciò che tolgo a questo è che è importante testare effettivamente i parametri di default per essere certi che non interrompano la correttezza del tipo quando si tenta di usarli!
Non una risposta, ma tre cose da notare: potreste voler dare al parametro del tipo qualcosa di diverso da "A" per evitare confusione con il (diverso) 'A' nel' trovato: [A] scala.collection. immutable.Set [A] 'messaggio; il fatto importante sia di 'Set' che di' Hallo' è che sono invarianti (al contrario di 'List'); e la tua ultima riga compilata probabilmente non fa quello che vuoi. –
Mentre 'class Bar [A] (hallo: Hallo [A] = Hallo.apply)' se lo si modifica per usare 'Hallo.apply()' funziona correttamente. Dovresti essere in grado di lasciare il paren spento, quindi dev'essere molto confuso qui. Pensa che stai passando la funzione parzialmente applicata 'Hallo.apply' invece di chiamare' apply' senza argomenti. (Il messaggio di errore dice che ha trovato il tipo '[A]() Hallo [A]'.) – DaoWen