Voici le scénario: J’ai écrit du code avec une signature de type et GHC n’a pas pu déduire x ~ y pour certains x
et y
. Vous pouvez généralement lancer GHC un os et simplement append l’isomorphisme aux contraintes de la fonction, mais c’est une mauvaise idée pour plusieurs raisons:
Je viens de passer plusieurs heures à affronter le cas 3. Je joue avec syntactic-2.0
et j’essayais de définir une version de share
indépendante du domaine, similaire à la version définie dans NanoFeldspar.hs
.
J’ai eu ceci:
{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-} import Data.Syntactic -- Based on NanoFeldspar.hs data Let a where Let :: Let (a :-> (a -> b) :-> Full b) share :: (Let : (a -> b) -> b) fi) => a -> (a -> b) -> a share = sugarSym Let
et GHC could not deduce (Internal a) ~ (Internal b)
, ce qui n’est certainement pas ce que j’allais faire. Donc, soit j’ai écrit du code que je n’avais pas l’intention (ce qui nécessitait la contrainte), soit GHC voulait cette contrainte en raison d’autres contraintes que j’avais écrites.
Il s’est avéré que je devais append (Syntactic a, Syntactic b, Syntactic (a->b))
à la liste des contraintes, aucune n’impliquant (Internal a) ~ (Internal b)
. Je suis tombé essentiellement sur les bonnes contraintes; Je n’ai toujours pas de façon systématique de les trouver.
Mes questions sont:
Internal a ~ Internal b
, alors d’où GHC tire-t-elle cela? Tout d’abord, votre fonction a le mauvais type; Je suis à peu près sûr que ce devrait être (sans le contexte) a -> (a -> b) -> b
. GHC 7.10 est un peu plus utile pour indiquer cela, car avec votre code d’origine, il se plaint d’une contrainte manquante Internal (a -> b) ~ (Internal a -> Internal a)
. Après avoir fixé le type de share
, GHC 7.10 rest utile pour nous guider:
Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))
Après avoir ajouté ce qui précède, nous obtenons Could not deduce (sup ~ Domain (a -> b))
Après avoir ajouté cela, nous obtenons Could not deduce (Syntactic a)
, Could not deduce (Syntactic b)
et Could not deduce (Syntactic (a -> b))
Après avoir ajouté ces trois éléments, il a finalement été détecté; donc on se retrouve avec
share :: (Let :<: sup, Domain a ~ sup, Domain b ~ sup, Domain (a -> b) ~ sup, Internal (a -> b) ~ (Internal a -> Internal b), Syntactic a, Syntactic b, Syntactic (a -> b), SyntacticN (a -> (a -> b) -> b) fi) => a -> (a -> b) -> b share = sugarSym Let
Je dirais donc que GHC n’a pas été inutile pour nous guider.
En ce qui concerne votre question sur le traçage où GHC obtient ses exigences de contrainte, vous pouvez essayer les indicateurs de débogage de GHC , en particulier -ddump-tc-trace
, puis lire le journal résultant pour voir où Internal (a -> b) ~ t
et (Internal a -> Internal a) ~ t
sont ajoutés à l’ensemble Wanted
, mais la lecture sera assez longue.