2014-11-13 10 views
9

Muovendo dalle this question, io non sono sicuro perché questi due frammenti di codice producono completamente diversi errori:Perché GHC produce un errore di vincolo di uguaglianza piuttosto che un errore di corrispondenza di tipo qui?

f :: a -> b 
f x = x 
-- Couldn't match expected type `b' with actual type `a' 
-- In the expression: x 

g :: Monad m => a -> m b 
g x = return x 
-- Could not deduce (a ~ b) from the context (Monad m) 
-- In the first argument of `return', namely `x'. 

Qual è la regola dando luogo a questo comportamento?

Non è molto leggibile, anche a qualcuno che ha familiarità con Haskell standard; il vincolo di uguaglianza (a ~ b) richiede un'estensione di lingua.

noti che, come chi sottolineato, la semplice presenza di un vincolo innesca l'errore di vincolo:

class C a 

h :: C a => a -> b 
h x = x 
-- Could not deduce... 

(Un vincolo vuoto, () => a -> b, dà la non corrispondenza dell'errore vincolo.)

+2

Aggiungere un contesto a 'f' e si attiverà l'errore di vincolo di uguaglianza: ad es. 'f :: Mostra a => a -> b' – chi

+1

Sebbene non sia strettamente sbagliato, il messaggio" Impossibile dedurre (a ~ b) "probabilmente non è molto buono in questo caso per un principiante che non è a conoscenza di cosa' ~ 'simbolo significa. Quindi per "perché" - direi che è un bug. – user2407038

risposta

6

Non penso che ci sia una risposta più breve che scavare negli interni di GHC per capire perché.

Se si esegue GHC con lo switch -ddump-tc-trace, è possibile ottenere un registro piuttosto lungo del processo di controllo ortografico. In particolare, se lo si esegue su questo codice:

f :: a -> b 
f x = x 

class C a 

h :: C c => c -> d 
h x = x 

si può vedere che typechecking a vs b, e typechecking c vs d progredisce esattamente nello stesso modo in entrambi i casi, si conclude con i seguenti due vincoli irrisolti (in uscita è da GHC 7.8.2):

tryReporters { [[W] cobox_aJH :: c ~ d (CNonCanonical)] 
... 
tryReporters { [[W] cobox_aJK :: a ~ b (CNonCanonical)] 

seguendo nella tana del coniglio un po 'più in TcErrors, si può vedere che per uguaglianze sul skolems, tryReporters ottiene finalmente a creare il messaggio di errore tramite misMatchOrCND, wh ich ha un caso speciale esplicito per contesti vuoti:

misMatchOrCND :: ReportErrCtxt -> Ct -> Maybe SwapFlag -> TcType -> TcType -> SDoc 
-- If oriented then ty1 is actual, ty2 is expected 
misMatchOrCND ctxt ct oriented ty1 ty2 
    | null givens || 
    (isRigid ty1 && isRigid ty2) || 
    isGivenCt ct 
     -- If the equality is unconditionally insoluble 
     -- or there is no context, don't report the context 
    = misMatchMsg oriented ty1 ty2 
    | otherwise 
    = couldNotDeduce givens ([mkTcEqPred ty1 ty2], orig) 
+0

Leggere in modo errato 'misMatchOrCND', non dovrebbe' isRigid ty1 && isRigid ty2' essere 'True'? Non tutti i tipi di gioco sono qui rigidi? –

+0

Vedere la definizione di 'isRigid' nello stesso modulo; Non vedo come potrebbe restituire True per qualsiasi tipo di variabile. Si noti che non è lo stesso di 'isRigidOrSkol'. – Cactus

Problemi correlati