Bisakah Template Haskell mengetahui nama dan / atau deklarasi dari sinonim tipe terkait yang dinyatakan dalam kelas tipe? Saya berharap reify
akan 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, InstanceD
tidak 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 reify
tidak 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 ").
InstanceD
seperti 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.
reify
tidak mengembalikan informasi yang diperlukan. Mungkin show
menyembunyikan beberapa informasi? Sudahkah Anda mencoba memeriksa Info
objek secara langsung?
Info
's Show
instance hanya berasal satu, dan sama untuk Show
contoh 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
?