Получение синонимов связанных типов с шаблоном Haskell


может ли шаблон Haskell узнать имена и / или объявления связанных синонимов типов, объявленных в классе типов? Я ожидал reify будет делать то, что я хочу, но он, кажется, не предоставляет всю необходимую информацию. Он работает для получения сигнатур типа функции:

% 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)))])
       []

однако добавление связанного синонима типа в класс не вызывает никаких изменений (вплоть до переименования) в выходных данных:

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)))])
       []

если я знаю имя F, Я могу посмотреть информацию об этом:

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

но я не могу найти имя F в первую очередь. Даже если я добавлю экземпляр класса type, то InstanceD не имеет никакой информации об определении:

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)))
                  []]

если reify не будет работать, есть ли обходной путь, кроме перечисления синонимов ассоциированного типа вручную?

эта проблема присутствует в GHC 7.8.3 с версией 2.9.0.0 пакета template-haskell; она также присутствовала в GHC 7.4.2 с версией 2.7.0.0 пакета template-haskell. (Я не проверял на GHC 7.6.* , но я думаю, что он присутствовал там тоже.) Меня интересуют решения для любой версии GHC (в том числе "это было исправлено только в версии GHC V").

1 252

1 ответ:

он не реализован, потому что его никто не просил.

странно то, что TH использует свой собственный AST, который не следует за внутренним компилятором AST. В результате любая новая функция (например, связанные семейства типов) не будет автоматически доступна через TH. Кто-то должен открыть билет и реализовать его.

Для справки: внутренний reifyClass функции игнорировать семей типа (это 5-й элемент кортежа, возвращаемого classExtraBigSig см. также определение ClassATItem.)

технически это должно быть легко реализовать связанную поддержку семейства типов в reify, но, скорее всего, это потребует обратных несовместимых изменений в Th API, например, потому что его AST, похоже, не поддерживает связанные значения по умолчанию типа.

добавлено: сейчас реализовала (без изменения API кстати) и, вероятно, будет доступен в следующем ghc освобождать.