2014-12-06 14 views
6

Occasionalmente mi imbatto in questo problema e alla fine ho voluto chiedere se esiste una soluzione o uno schema comune. È possibile rendere una variabile di tipo in un contesto annidato fare riferimento a un tipo da un contesto esterno? Per esempio,Haskell Riferimento a una variabile di tipo

foo :: a -> ... -> .. 
foo = ... 
    where bar :: a -> ... 

Ora bar s' a è diverso da quello di foo a. Tipicamente questo è quello che voglio, ma a volte rende la vita difficile, e ho bisogno di renderli uguali. Ho usato trucchi sporchi per forzare il correttore di tipi a unificare i due in passato, ma a volte sono stati ostacolati. Ecco il mio ultimo esempio (una funzione di Parsec) che mi ha spinto a porre finalmente questa domanda.

data Project = ... deriving Enum 
data Stuff = ... 

pProject :: Monad m => P m Stuff 
pProject = do 
    stuff <- pStuff 
    ... 
    convert stuff <$> pEnum :: P m Project 

pEnum :: (Monad m, Enum a) => String -> P m a 
pEnum = ... 

La funzione convert necessario un tipo, quindi ho dovuto specificare l'annotazione :: P m Project. Tuttavia, ciò significa che devo anche introdurre lo m, che sfortunatamente non è lo stesso m come nella firma della funzione. Le relazioni checker tipo questo con:

Impossibile dedurre Monad m1 derivante da un uso del pEnum dal contesto Monad m

Esiste un modo per fare riferimento alla funzione del m firma senza qualche brutto hack? (Un brutto attacco sarebbe l'inserimento di un codice fittizio che non viene eseguito, ma esiste solo per unificare i due tipi.)

risposta

13

Si sta cercando l'estensione ScopedTypeVariables, che consente di fare riferimento alle variabili di tipo dal contenere gli ambiti.

{-# LANGUAGE ScopedTypeVariables #-} 

Per compatibilità all'indietro, si applica solo a digitare le firme che hanno un esplicito forall. Così si avrebbe dovuto scrivere:

pProject :: forall m. Monad m => P m Stuff 

Dopo di che, si sarebbe in grado di fare riferimento al tipo corretto variabile m all'interno del campo di applicazione del pProject.

+5

Grazie per aver sottolineato che "ScopedTypeVariables" si applica solo alle firme con un esplicito 'forall'. Non c'è da stupirsi che non abbia quasi mai funzionato ... – Cirdec

+3

Non è del tutto vero - 'ScopedTypeVariables' rende le variabili di tipo circoscritte nelle dichiarazioni di classe anche senza' forall'. Così può cambiare il significato di un programma di Haskell 2010 inventato. – shachaf

Problemi correlati