Чи може Шаблон 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 пакета шаблон-haskell; він також був присутній у GHC 7.4.2 з версією 2.7.0.0 пакета шаблон-haskell. (Я не перевіряв GHC 7.6. *, Але, думаю, він там також був присутній.) Мене цікавлять рішення для будь-якої версії GHC (включаючи "це було виправлено лише у GHC версії V ").
InstanceD
що я бачив із 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
?