TL; la risposta di DR JJ è giusta, ma la spiegazione mi ha lasciato confuso. Attualmente vedo il problema che hai mostrato come errore / bug di autovivificazione e / o messaggio di errore LTA.
say my Any $Any; # (Any)
say my Hash $Hash; # (Hash)
say my Hash[Int] $Hash-Int; # (Hash[Int])
$Any<a> = 42; # OK
$Hash<a> = 42; # OK
$Hash-Int.new<a> = 42; # OK
$Hash-Int<a> = 42; # must be an object instance, not a type object
Imo questo è un bug o abbastanza vicino a uno.
Un bug / problema si applica anche alle matrici nello stesso scenario:
say my Any $Any; # (Any)
say my Array $Array; # (Array)
say my Array[Int] $Array-Int; # (Array[Int])
$Any[42] = 42; # OK
$Array[42] = 42; # OK
$Array-Int.new[42] = 42; # OK
$Array-Int[42] = 42; # Type check failed ... expected Array[Int] but got Array
Se è meglio considerare notabug, forse il messaggio di errore dovrebbe essere modificato. Sebbene io sia d'accordo con JJ sul fatto che il messaggio di errore sia effettivamente in questione (quando capisci come funziona raku e capisci cosa sta succedendo), penso che sia comunque un messaggio di errore LTA se non cambiamo raku (do) in dwim.
D'altra parte, non è ovvio per me come si possa migliorare al meglio il messaggio di errore. E ora abbiamo questo SO. (cfr. il mio punto al riguardo in È il ... messaggio di errore LTA? in una risposta recente che ho scritto .)
Un'altra soluzione
Ho già provato il %
sigillo per la variabile hash, che non funziona neanche.
JJ ha fornito una soluzione che si inizializza con un valore con un esplicito .new
. Ma questo elimina il vincolo dalla variabile. Per conservarlo:
class Foo {}
constant FooFoo = Hash[Foo:D,Foo:D];
my %foo is FooFoo;
%foo{Foo.new} = Foo.new;
Idealmente constant
non sarebbe necessario, e forse un giorno non lo sarà, ma penso che l'analisi del tratto sia limitata.