7
votes

Haskell: "Impossible de déduire" Erreur avec Runst

Lorsque j'essaie de compiler ceci:

Could not deduce (t ~ U.MVector s a)
    from the context (U.Unbox a)
      bound by the inferred type of myRead :: U.Unbox a => t -> a
      at src/Main.hs:53:1-32
      `t' is a rigid type variable bound by
          the inferred type of myRead :: U.Unbox a => t -> a
          at src/Main.hs:53:1
    Expected type: U.MVector (PrimState (ST s)) a
      Actual type: t
    In the first argument of `MV.read', namely `mv'
    In the second argument of `($)', namely `MV.read mv 0'
    In the expression: runST $ MV.read mv 0


2 commentaires

Je pense que l'opinion du sage, de Viz Breitner et de Fischer, c'est que nous devons en savoir plus sur la façon dont vous êtes arrivé à ce point. Quelle fonction produisent le vecteur mutable que vous proposez d'appliquer maread? Voir la dernière phrase de la réponse de Breitner. Si nous savions ce que nous vous mettais dans ce coin, nous pourrions dire comment réanifier les choses afin qu'elles pendent ensemble. Quelques lignes de code supplémentaires seraient donc utiles. Par exemple, si MV est à l'intérieur d'un bloc ST, la définition plus simple mradre mv = mv.read mv 0 (no runst ) pourrait être utilisé .


Permettez-moi de renforcer ce que l'application a dit: nous avons besoin de plus de contexte. Sans savoir ce que vous voulez réellement atteindre, nous ne pouvons pas trouver la solution appropriée.


3 Réponses :


3
votes

Le compilateur par défaut de voir l'argument MV code> sur le côté gauche à partir d'un type spécifique, mais nécessite quelque chose de type polymorphe à droite. Une signature de type peut corriger les choses.

mhead :: MV.Unbox a => MV.MVector s a -> ST s a
mhead mv0 =  MV.read mv0 0

mrx  = runST $ do mv <- UV.unsafeThaw $ UV.enumFromStepN 0 1 20
                             -- ^^^ or however the mv is generated.
                  x <- MV.unsafeRead mv 17 -- arbitrary 'scratch pad'
                  MV.unsafeWrite mv 17 (2*x)  -- computations
                  mhead mv
                  -- ^^^ we return just the first element, after all the mutation


0 commentaires

3
votes

La réponse par Applicatif vous indique comment amener votre code à compiler. Mais le code ne sera pas utilisable: le point de runst est que le calcul impératif ne peut pas s'échapper, en raison de la variable de type liée existante là-bas.

Maintenant tout matrice mutable que vous créez quelque part aura de type mvector SA pour un fixe s, tandis que votre myread attend une valeur qui fournit une valeur fournie Un vecteur pour tout s.

Il semble qu'il y ait un problème plus tôt qui vous a fait vouloir avoir cette fonction (impossible).


4 commentaires

Je conviens que c'est une fonction indésirable, j'essayais d'expliquer l'erreur de type. Est l'explication inepte? Si oui, je devrais le supprimer. Je pensais à l'écrivain comme un accroché à la manière dont l'inférence de type fonctionne avec St.


@Applicatif non, l'explication va bien. Ajouter peut-être que la fonction serait inutilisable, de sorte que les deux réponses ont ce fait important.


Je ne peux pas dire que j'ai compris une grande partie de ce que vous avez dit ci-dessus, cependant, je me demandais si vous pouviez plus expliquer pourquoi cette fonction est impossible. Le contexte est que j'ai une fonction qui prend dans un vecteur mutable, fait quelques calculs utilisant le vecteur mutable comme un espace à gratter temporaire, puis doit renvoyer une valeur de flotteur. Parce que je me fiche des changements sur le vecteur mutable, je me demandais s'il y avait un moyen d'ignorer son "changement d'état" et de renvoyer simplement l'une des valeurs de l'intérieur.


Il existe une manière multiple pour une fonction ne pas pure. Une évidence est si elle modifie les données. MyRead ne fait pas cela, et il semble vous faire croire que cela devrait être donc possible de le définir avec un type pur. Mais une autre cause d'impureté est si la valeur de la fonction dépend, par ex. le temps qu'il est évalué. Et ceci est le cas ici: myread appliqué à un vecteur donnera des résultats différents pour le même vecteur, si le vecteur a été modifié entre les deux. Par conséquent, myread doit avoir un type monadique.



2
votes

Les autres réponses sont bonnes, mais je pense qu'il y a une chose fondamentale à propos de ST que vous manquez. Chaque appel à Runst fait efficacement un nouvel "ST Universe" dans lequel un code impératif est exécuté. Donc, si vous avez un appel à Downst pour faire le tableau et un appel séparé à Runst pour obtenir une valeur de cette matrice, les choses ne peuvent pas être fonctionnelles. Les deux appels à Runst veulent leurs propres univers uniques, alors que vous voulez qu'ils partagent un.

Quelles sont les réponses expliquées dans certains détails, c'est la manière dont ces univers uniques sont créés par une supercherie de type type.


1 commentaires

Cette. Runst est censé avoir l'air pur de l'extérieur, et rien de mutable ne peut s'échapper du St monad.