Voici le scénario: j'ai écrit du code avec une signature de type et GHC se plaint de ne pas pouvoir déduire x ~ y pour certains x
et y
. Vous pouvez généralement jeter un os à GHC et ajouter simplement l'isomorphisme aux contraintes de fonction, mais ceci est une mauvaise idée pour plusieurs raisons:
Je viens de passer plusieurs heures à lutter contre le cas 3. Je joue avec syntactic-2.0
, et j’essayais de définir une version de share
indépendante du domaine, similaire au 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 :<: sup,
Domain a ~ sup,
Domain b ~ sup,
SyntacticN (a -> (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 je voulais faire. Donc, soit j'avais écrit un code que je n'avais pas l'intention de créer (ce qui nécessitait la contrainte), soit GHC voulait cette contrainte en raison de certaines autres contraintes que j'avais écrites.
Il s'est avéré que je devais ajouter (Syntactic a, Syntactic b, Syntactic (a->b))
À la liste des contraintes, aucune de celles-ci n'impliquant (Internal a) ~ (Internal b)
. Je suis essentiellement tombé sur les contraintes correctes; Je n'ai toujours pas de moyen systématique pour les trouver.
Mes questions sont:
Internal a ~ Internal b
, Alors d'où GHC a-t-il tiré cela?Tout d'abord, votre fonction a le mauvais type; Je suis à peu près sûr que cela devrait être (sans le contexte) a -> (a -> b) -> b
. GHC 7.10 est un peu plus utile pour le signaler, car avec votre code d'origine, il se plaint d'une contrainte manquante Internal (a -> b) ~ (Internal a -> Internal a)
. Après avoir corrigé le type de share
, GHC 7.10 reste 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 l’ajout de ces trois éléments, il est enfin possible 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
Donc, je dirais que GHC n'a pas été inutile pour nous guider.
En ce qui concerne votre question sur le traçage d'où GHC tire ses exigences de contrainte, vous pouvez essayer indicateurs de débogage de GHC , en particulier, -ddump-tc-trace
, Puis consultez 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.