Bisakah Template Haskell mengetahui nama dan / atau deklarasi dari sinonim tipe terkait yang dinyatakan dalam kelas tipe? Saya berharap reifyakan melakukan apa yang saya inginkan, tetapi sepertinya tidak memberikan semua informasi yang diperlukan. Ini berfungsi untuk mendapatkan tanda tangan jenis fungsi:
% 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)))])
[]
Namun, menambahkan sinonim tipe terkait ke kelas menyebabkan tidak ada perubahan (hingga penamaan ulang) di 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)))])
[]
Jika saya tahu nama F, saya dapat mencari informasi tentang itu:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Tapi saya tidak dapat menemukan nama itu F. Bahkan jika saya menambahkan turunan dari kelas tipe, InstanceDtidak ada informasi tentang definisi:
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)))
[]]
Jika reifytidak berhasil, apakah ada solusi, selain mendaftar sinonim jenis rekanan secara manual?
Masalah ini hadir di GHC 7.8.3 dengan versi 2.9.0.0 dari paket template-haskell; itu juga hadir di GHC 7.4.2 dengan versi 2.7.0.0 dari paket template-haskell. (Saya tidak memeriksa GHC 7.6. *, Tapi saya membayangkan itu ada di sana juga.) Saya tertarik dengan solusi untuk semua versi GHC (termasuk "ini hanya diperbaiki di GHC versi V ").
InstanceDseperti yang saya lihat dengan reify: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])mengevaluasi [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []], yang tidak memiliki contoh keluarga jenis.
reifytidak mengembalikan informasi yang diperlukan. Mungkin showmenyembunyikan beberapa informasi? Sudahkah Anda mencoba memeriksa Infoobjek secara langsung?
Info's Showinstance hanya berasal satu, dan sama untuk Showcontoh untuk Dec. Namun, saya juga dapat memeriksa secara langsung, seperti yang Anda minta, dan tidak: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")menghasilkan just a SigD- itu benar-benar satu-satunya di [Dec]dalam ClassD! (membutuhkan LambdaCase). Saya setuju itu aneh; itu sebabnya saya menanyakan pertanyaan ini :-)
reifyInstances?