Ecco lo scenario: ho scritto del codice con una firma di tipo e le lamentele di GHC non sono state in grado di dedurre x ~ y per alcuni x
e . Di solito puoi lanciare GHC un osso e aggiungere semplicemente l'isomorfismo ai vincoli di funzione, ma questa è una cattiva idea per diversi motivi:Tecniche per i vincoli di traccia
- Non enfatizza la comprensione del codice.
- Si può finire con 5 vincoli in cui uno sarebbe sufficiente (per esempio, se il 5 è implicito da un vincolo più specifico)
- Si può finire con vincoli fasulli se hai fatto qualcosa di sbagliato o se GHC viene inutile
ho appena trascorso diverse ore in lotta caso 3. sto giocando con syntactic-2.0
, e stavo cercando di definire una versione indipendente dal dominio di share
, simile alla versione definita in NanoFeldspar.hs
.
ho avuto questo:
{-# 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
e GHC could not deduce (Internal a) ~ (Internal b)
, che non è certo quello che stavo per. Quindi o avevo scritto del codice che non intendevo (che richiedeva il vincolo), o GHC voleva quel vincolo a causa di altri vincoli che avevo scritto.
È risultato necessario aggiungere (Syntactic a, Syntactic b, Syntactic (a->b))
all'elenco dei vincoli, nessuno dei quali implica (Internal a) ~ (Internal b)
. Fondamentalmente sono incappato sui vincoli corretti; Non ho ancora un modo sistematico per trovarli.
Le mie domande sono:
- Perché GHC propongo vincolo? Da nessuna parte in sintattica c'è un vincolo
Internal a ~ Internal b
, quindi da dove ha tratto il GHC? - In generale, quali tecniche possono essere utilizzate per tracciare l'origine di un vincolo che GHC ritiene sia necessario? Anche per i vincoli che io posso trovare , il mio approccio è essenzialmente quello di forzare brutalmente il percorso incriminato scrivendo fisicamente dei vincoli ricorsivi. Questo approccio sta fondamentalmente andando a scapito di una spirale infinita di vincoli e riguarda il metodo meno efficiente che io possa immaginare.
Ci sono state discussioni su un debugger a livello di codice, ma il consenso generale sembra mostrare che la logica interna del typechecker non aiuterà:/A partire da ora il risolutore di vincoli di Haskell è un linguaggio logico opaco e schifoso :) – jozefg
@jozefg Avete un collegamento per quella discussione? – crockeea
Spesso aiuta a rimuovere completamente la firma del tipo e lascia che ghci ti dica quale dovrebbe essere la firma. –