Может ли Template 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
в первую очередь. Даже если я добавлю экземпляр класса типа, у 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 »).
InstanceD
s, что я видел с reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
оценивает [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, которому не хватает экземпляров семейства типов.
reify
не возвращает необходимую информацию. Возможно show
, скрывает часть информации? Вы пытались исследовать Info
объект напрямую?
Info
, Show
экземпляр только производный, и то же самое для Show
экземпляра для Dec
. Тем не менее, я также могу проверить напрямую, как вы просили, и нет: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
производит just a SigD
- это действительно единственная вещь [Dec]
в ClassD
! (требуется LambdaCase
). Я согласен, это странно; вот почему я задал этот вопрос :-)
reifyInstances
?