Les types d'arguments d'une fonction anonyme doivent être entièrement connus. (SLS 8.5)

j'ai une fonction littérale

{case QualifiedType(preds, ty) =>
               t.ty = ty ;
               Some((emptyEqualityConstraintSet,preds)) }

ce qui donne un message d'erreur

missing parameter type for expanded function The argument types of an anonymous function
must be fully known. (SLS 8.5) Expected type was:
? => Option[(Typer.this.EqualityConstraintSet, Typer.this.TypeRelationSet)]

j'ai regardé dans SLS 8.5, mais n'a pas trouver une explication.

si je développe la fonction moi-même à

{(qt : QualifiedType) =>
  qt match {case QualifiedType(preds, ty) =>
               t.ty = ty ;
               Some((emptyEqualityConstraintSet,preds)) }}

l'erreur disparaît.

(A) pourquoi s'agit-il d'une erreur?

b) Que puis-je faire pour corriger la situation?

j'ai essayé la correction évidente, qui était d'ajouter : QualifiedType entre le modèle et l' =>, mais c'est un erreur de syntaxe.


Une chose que j'ai remarqué, c'est que le contexte fait une différence. Si j'utilise la fonction littéral comme argument à une fonction déclarée comme attente d'un QualifiedType => B, il n'y a pas d'erreur. Mais si je l'utilise comme argument à une fonction qui attend une A => B, il y a une erreur. Je pense que ce qui se passe ici est que, comme le modèle pourrait être appliqué à un objet dont le type est un supertype de QualifiedType, le compilateur n'est pas disposé à céder la type évident sans assurance que la fonction ne sera pas appliquée à quoi que ce soit qui n'est pas un type qualifié. Ce que j'aimerais vraiment, c'est pouvoir écrire {QualifiedType( preds, ty) => ...} et ont-il dire la même chose que Haskell QualifiedType(preds,ty) -> ....

25
demandé sur Mario Galic 2012-10-13 05:48:52

3 réponses

Voici le SLS citation, pour le reste d'entre nous:

Le type attendu d'une telle expression doit en partie être défini. Il doit être scala.Functionk[S1, . . . , Sk, R] pour quelques k > 0, ou scala.PartialFunction[S1, R], où le(S) Type (S) d'argument S1, . . . , Sk doit être entièrement déterminée, mais le résultat du type R peut être indéterminé.

Sinon, vous avez répondu à votre question.

7
répondu som-snytt 2017-10-27 07:12:32

{ case X(x) => ... } est une fonction partielle, mais le compilateur ne sait toujours pas quel est votre type d'entrée, sauf que c'est un supertype de X. Normalement ce n'est pas un problème parce que si vous écrivez une fonction anonyme, le type est connu du contexte. Mais voici comment vous pouvez fournir le type:

case class Foo(x: Int)

// via annotation
val f: Foo => Int = { case Foo(x) => x }

// use pattern matching
val f = (_: Foo) match { case Foo(x) => x }

// or more normally, write as a method
def f(a: Foo) = a match { case Foo(x) => x }
def f(a: Foo) = a.x

comme vous l'avez probablement remarqué, l'utilisation de la fonction correspondance littérales / motifs ici est assez inutile. Il semble dans votre cas que vous avez juste besoin d'un régulier méthode:

def whatever(qt: QualifiedType) = {
  t.ty = qt.ty
  Some((emptyEqualityConstraintSet, qt.preds)) 
}

bien que vous devriez réfléchir pour supprimer cet état mutable.

18
répondu Luigi Plinge 2012-10-13 03:06:26

Voici pourquoi j'ai voulu utiliser une fonction littérale et n'ai pas aimé avoir à répéter le type deux fois. J'essayais de construire ma propre construction de contrôle pour éliminer toutes les options correspondant au code. S'il y a trop de frais généraux, alors la structure de contrôle n'aide pas. Voici ce que je voulais faire

//This is the control construct definition
def switch[A,B]( x : Option[A], noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

//And this is an example of using it.
def foobar( qt : Option[QualifiedType]  ) = 
    switch( qt, {reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

la construction de la commande d'interrupteur se compile bien, mais l'usage a causé une erreur parce que le SLS dit que là où j'ai un A, je devrais avoir un "type défini". C'est parce que ce genre de fonction littérale (le genre avec "cas") est destiné à des fonctions partielles où l'argument pourrait être légitimement n'importe quelle chose du tout. Je pourrais argumenter ma fonction littérale avec un int et ce ne serait pas une erreur de type, mais simplement une question de tous les modèles échouant. Donc le compilateur a besoin de quelques informations "top down" pour savoir quel type j'ai l'intention de mettre pour le paramètre de la "fonction étendue littérale", c'est-à-dire ce qu'il faut mettre pour X dans les

{(x : X) => x match {case Some(QualifiedType(preds, ty)) =>
               Some((emptyEqualityConstraintSet,preds)) } }

je me demande pourquoi le compilateur ne pouvait pas utiliser le type de commutateur pour voir que je n'ai pas l'intention d'une fonction partielle et puis unifier A avec QualifiedType. Mais ça ne marche pas.

de toute façon il ne compile pas. Mais remplacer A par Any élimine l'erreur. Le code suivant se compile. Ce que je perds, c'est une vérification de type.

//This is the control construct definition
def switch[A,B]( x : Option[A], noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

//And this is an example of using it.
def foobar( qt : Option[QualifiedType]  ) = 
    switch( qt, {reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

je serais intéressé de savoir (a) si la définition ci-dessus de commutateur peut être améliorée, et (b) s'il y a déjà une fonction de bibliothèque qui fait ce que je vouloir.


ajouté après le commentaire de Luigi

Voici le code final. Oui, je pense que c'est un pli (catamorphisme).

def switch[A,B]( x : Option[A])(noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

def foobar( qt : Option[QualifiedType]  ) : Option[(EqualityConstraintSet, TypeRelationSet)] =
    switch( qt )({reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

merci à Luigi.

4
répondu Theodore Norvell 2015-04-07 12:45:04