11
votes

Type de base inferral

Veuillez considérer Classe de la case FOO [A, B <: liste [a]] (L: B) {...} ou quelque chose d'appartement. En particulier, a ainsi que B doit être disponible quelque part dans le corps de FOO .

est-il possible pour le compilateur d'infère A automatiquement? Par exemple, foo (liste (1,2,3)) échoue car le vérificateur de type infère A comme rien . Peut-être qu'il y a un moyen en utilisant des membres de type pour résoudre ce problème?

J'ai ce sentiment que je suis négligeant quelque chose d'embarcence simple ici;)

EDIT: je viens de découvrir qu'utilisant un autre paramètre type x fonctionne juste bien, mais guichet automatique Je ne comprends pas pourquoi c'est le cas: xxx

peut-il s'il vous plaît expliquer cela à moi? est-ce un problème d'unification?

EDIT 2: Utilisation de [A, B [x] <: liste [x]] (L: B [A]) / code> peut avoir des implications indésirables pour certaines hiérarchies (bien que ce ne soit pas vraiment une grosse affaire). Plus de conclusions intéressant, je viens de tomber sur un publication du blog par Josh SUERETH Cela montre implicitement que [a, b <: liste [a]] (L: B avec la liste [A]) fonctionne aussi bien ... pas besoin de implicite, etc. < / p>


2 commentaires

Pouvez-vous définir la classe comme Classe de cas FOO [A] (L: liste [A]) ? Cela pourrait être plus clair.


Je comprends ce que vous voulez dire, mais ce n'est pas applicable dans mon scénario. Les deux types A et B doivent être connus les uns des autres.


3 Réponses :


5
votes

Cela ne répond pas vraiment à la partie "Pourquoi", désolé, mais voici quelques astuces supplémentaires que vous pouvez jouer. Tout d'abord, puisque vous n'utilisez pas le x dans votre exemple, vous pouvez écrire: xxx

puis: xxx

(J'utilise le covariant SEQ au lieu de Liste pour montrer qu'il fonctionne également pour les sous-types. Aussi, notez que cela ne correspond pas à l'utilisation du supplément x , voir les commentaires.) Malheureusement, chaque fois que vous souhaitez utiliser le type de séquence, vous devez écrire b [a] , c'est-à-dire l'instancier manuellement. Une façon de contourner cela consiste à écrire à la place: xxx

in action: xxx

... et vous obtenez Les paramètres de type a et b instancié comme si vous saviez toujours qu'ils devraient.


4 commentaires

C'est mauvais conseil. N'écrivez jamais "B [] <: SEQ []", cela ne signifie pas ce que vous pensez. Il utilise effectivement le X, pour lier le paramètre de type B de B sur SEQ. Les soulignés dans "B [] <: SEQ []" ne sont pas le même type.


Outre le problème _ , j'ai trouvé cela dans un poste intéressant car je n'aurais jamais deviné qu'une vue implicite pourrait aider. Alors, où le compilateur trouve-t-il une vue implicite pour B comme SEQ [A] ? Lorsque j'ai essayé dans la console, il a trouvé une fonction de Predef, mais cela fonctionne également avec des classes personnalisées (apparemment, il n'est pas possible d'avoir des exemples joliment formatés dans cette section, désolé). Y a-t-il un moyen de suivre ce qui implique le compilateur tire?


Ah, ok, en regardant la source de PreDef révèle l'infrastructure de <: <, =: = et <% <.


Désolé, cette première partie n'était pas si claire. Ils ne sont vraiment pas équivalents, et b [_] <: SEQ [_] est vraiment b [x] foresome {type x; } <: SEQ [Y] FORSOME {TYPE Y; } . Mon point était, dans ce cas Peu importe ce que le célibataire x ou les deux existentiels _ s est attribué, parce que vous ne voulez jamais Utilise les. Pour tout ce que vous savez x est affecté au joli inutile tout et mes deux existentielles à rien et tout respectivement , mais b [a] est ce qui compte à la fin.



5
votes

Il n'est pas possible que le compilateur infère automatiquement. Mais si cela était possible, il faudrait dire que cela devrait être un Superype de Int, donc int ou tout, pas seulement int! Int!. Parce qu'une liste [int] <: liste [tout]. Donc, si le compilateur déduirait Int pour un ce serait trop restrictif.

En d'autres termes:

  1. Classe de la case FOO [A, B <: liste [A]] (L: B) {...} puis l'appelant comme foo (liste (1,2,3)) Vous dites que un type doit être un type pour lequel une liste devrait être une super-équipée d'une liste de la liste des Int . Donc, efficacement, un super-espèce d'int car la liste est Covariant.

  2. Barre de la classe [A, B [x] <: liste [x]] (L: B [A]) et ensuite l'appelant comme foo (liste (1,2,3)) vous dites que un doit être un int .

    Case (2) ne laisse aucune place à un autre que Int. Case (1) Cependant, laisse la place pour être quelque chose d'autre que INT, par ex. Cela pourrait être tout. Vous pouvez voir cela parce que vous pourriez l'appeler par foo [tout, liste [int]] (liste (1,2,3)) . Vous ne seriez pas capable de le faire au cas où (2).

    Les deux cas ne sont pas équivalents.


4 commentaires

Merci, que foo [Tout, liste [int]]]] est un bon. Otoh, je me demande pourquoi, à la suite de votre raisonnement, il est toujours impossible de dire quelque chose comme foo [a, b>: liste [a] <: liste [a]] parce que ce serait, d'une logique point de vue, retirez l'ambiguïté (ou n'est-ce pas, je me demande?). Pourtant, dans les deux cas, c'est-à-dire que ce dernier ainsi que celui mentionné dans mon poste d'origine, le compilateur déduit A comme rien et continue de se plaindre de cela (compréhensible de mon point limité de la vue) C'est pourquoi je pense que outre la question de la covariance, cela peut également être expliqué en termes d'unification?


Oui en effet, je suis votre raisonnement. Je suppose que c'est ce que l'on entend avec le type de type Scala est incomplet.


Il y a ce très sympa Talk de Daniel SpoWack sur (non seulement Scala's) Inférence de type incomplète. L'intro est assez longue mais toute la conversation en vaut la peine.


A annexé une nouvelle "perspicacité" à mon message d'origine, juste au cas où vous êtes intéressé.



2
votes

Selon Alexey Romanov , en principe, le type pourrait être déduit automatiquement mais tout simplement pas à l'époque.

Donc, au moins pour l'instant, tous les paramètres de type qui doivent être déduits doivent apparaître explicitement dans les arguments.


0 commentaires