Ottenere sinonimi di tipo associati con il modello Haskell


257

Template Haskell può scoprire i nomi e / o le dichiarazioni dei sinonimi di tipo associati dichiarati in una classe di tipo? Mi aspettavo che reifyavrebbe fatto quello che volevo, ma non sembra fornire tutte le informazioni necessarie. Funziona per ottenere le firme dei tipi di funzione:

% ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
...
Prelude> -- I'll be inserting line breaks and whitespace for clarity
Prelude> -- in all GHCi output.
Prelude> :set -XTemplateHaskell 
Prelude> import Language.Haskell.TH
Prelude Language.Haskell.TH> class C a where f :: a -> Int
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C)
ClassI (ClassD [] Ghci1.C [PlainTV a_1627398388] []
               [SigD Ghci1.f
                     (ForallT [PlainTV a_1627398388]
                              [ClassP Ghci1.C [VarT a_1627398388]]
                              (AppT (AppT ArrowT (VarT a_1627398388))
                                    (ConT GHC.Types.Int)))])
       []

Tuttavia, l'aggiunta di un sinonimo di tipo associato alla classe non provoca alcuna modifica (fino alla ridenominazione) nell'output:

Prelude Language.Haskell.TH> :set -XTypeFamilies 
Prelude Language.Haskell.TH> class C' a where type F a :: * ; f' :: a -> Int
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
               [SigD Ghci3.f'
                     (ForallT [PlainTV a_1627405973]
                              [ClassP Ghci3.C' [VarT a_1627405973]]
                              (AppT (AppT ArrowT (VarT a_1627405973))
                                    (ConT GHC.Types.Int)))])
       []

Se conosco il nome di F, posso cercare informazioni al riguardo:

Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
                 Ghci3.F
                 [PlainTV a_1627405973]
                 (Just StarT))
        []

Ma non riesco a trovare il nome Fin primo luogo. Anche se aggiungo un'istanza della classe type, InstanceDnon contiene alcuna informazione sulla definizione:

Prelude Language.Haskell.TH> instance C' [a] where type F [a] = a ; f' = length
Prelude Language.Haskell.TH> f' "Haskell"
7
Prelude Language.Haskell.TH> 42 :: F [Integer]
42
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
               [SigD Ghci3.f'
                     (ForallT [PlainTV a_1627405973]
                              [ClassP Ghci3.C' [VarT a_1627405973]]
                              (AppT (AppT ArrowT (VarT a_1627405973))
                                    (ConT GHC.Types.Int)))])
       [InstanceD []
                  (AppT (ConT Ghci3.C')
                        (AppT ListT (VarT a_1627406161)))
                  []]

Se reifynon funziona, esiste una soluzione alternativa, oltre a elencare manualmente i sinonimi del tipo associato?

Questo problema è presente in GHC 7.8.3 con la versione 2.9.0.0 del pacchetto template-haskell; era presente anche in GHC 7.4.2 con la versione 2.7.0.0 del pacchetto template-haskell. (Non ho controllato GHC 7.6. *, Ma immagino che fosse presente anche lì.) Sono interessato a soluzioni per qualsiasi versione di GHC (incluso "questo è stato risolto solo nella versione V di GHC ").


2
Hai visto reifyInstances?
Kwarrtz,

2
@Kwarrtz: l'ho appena provato ora. Tuttavia, non funziona; dà origine alle stesse cose InstanceDche ho visto con reify: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])valuta [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []], a cui mancano le istanze della famiglia di tipi.
Antal Spector-Zabusky

1
Trovo strano che reifynon restituisca le informazioni necessarie. Forse shownasconde alcune delle informazioni? Hai provato a esaminare l' Infooggetto direttamente?
Kwarrtz,

@Kwarrtz: temo che Infol' Showistanza sia solo quella derivata, e lo stesso per l' Showistanza di Dec. Tuttavia, posso anche verificare direttamente, come lei ha chiesto, e non: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")produce just a SigD- che è in realtà l'unica cosa che nel [Dec]nel ClassD! (richiede LambdaCase). Sono d'accordo è strano; ecco perché ho posto questa domanda :-)
Antal Spector-Zabusky il

1
@Abel: Penso che siamo d'accordo violenta - il commento originale detto che non era abbastanza per attirare una brillante idea, ma ha fatto attirare la risposta di Yuras! Sono assolutamente d'accordo su quale sia una buona risposta :-)
Antal Spector-Zabusky,

Risposte:


15

Non è implementato perché nessuno lo ha richiesto.

La cosa strana è che TH usa il proprio AST, che non segue l'AST interno del compilatore. Di conseguenza, qualsiasi nuova funzione (ad es. Famiglie di tipi associati) non è automaticamente disponibile tramite TH. Qualcuno deve aprire un biglietto e implementarlo.

Per riferimento: la reifyClassfunzione interna ignora le famiglie di tipi associati (è il 5 ° elemento della tupla restituito da classExtraBigSig, vedere anche la definizione di ClassATItem.)

Tecnicamente dovrebbe essere facile implementare il supporto della famiglia di tipi associati reify, ma molto probabilmente richiederà modifiche incompatibili all'indietro nell'API TH, ad esempio perché il suo AST non sembra supportare le impostazioni predefinite dei tipi associati.

Aggiunto: ora è implementato (senza cambio API tra l'altro) e probabilmente sarà disponibile nella prossima ghcversione.


1
@ AntalS-Z Voglio dire che FamilyDnon supporta i valori predefiniti dei sinonimi associati . Probabilmente non li stai usando, ma la soluzione completa potrebbe richiedere una modifica dell'API.
Yuras,

5
@Abel, lasciare aperta la generosità fino alla fine tende anche ad aiutare le buone risposte ad attirare voti, quindi è un modo più efficace per premiare una buona risposta piuttosto che assegnarla rapidamente.
dfeuer,

1
Il periodo di ricompensa è scaduto. Questa è la migliore (e unica) risposta, fino a quando o a meno che la segnalazione di bug n. 10891 non venga risolta . Forse è una buona idea includere un link alla segnalazione di bug nella tua risposta.
Abel,

1
Cordiali saluti, # 10891 è stato risolto ed è in attesa di essere unito.
Sinan,

1
@SwiftsNamesake Gli sviluppatori AFAIK ghc vogliono cambiare liberamente l'AST interno senza rompere l'API TH. Probabilmente ci sono anche altri motivi.
Yuras,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.