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 ").
sumber
reifyInstances
?InstanceD
seperti yang saya lihat denganreify
: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. Mungkinshow
menyembunyikan beberapa informasi? Sudahkah Anda mencoba memeriksaInfo
objek secara langsung?Info
'sShow
instance hanya berasal satu, dan sama untukShow
contoh untukDec
. 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")
menghasilkanjust a SigD
- itu benar-benar satu-satunya di[Dec]
dalamClassD
! (membutuhkanLambdaCase
). Saya setuju itu aneh; itu sebabnya saya menanyakan pertanyaan ini :-)Jawaban:
Itu tidak diterapkan karena tidak ada yang memintanya.
Yang aneh adalah bahwa TH menggunakan AST sendiri, yang tidak mengikuti AST kompiler internal. Akibatnya, fitur baru apa pun (mis. Keluarga tipe terkait) tidak tersedia secara otomatis melalui TH. Seseorang harus membuka tiket dan menerapkannya.
Untuk referensi:
reifyClass
fungsi internal mengabaikan keluarga tipe terkait (ini adalah elemen ke-5 dari tuple yang dikembalikan olehclassExtraBigSig
, lihat juga definisiClassATItem
.)Secara teknis seharusnya mudah untuk menerapkan dukungan keluarga tipe terkait
reify
, tetapi kemungkinan besar itu akan memerlukan perubahan yang tidak kompatibel ke belakang di TH API, misalnya karena AST tampaknya tidak mendukung default jenis terkait.Ditambahkan: Sekarang diterapkan (tanpa perubahan API btw) dan mungkin akan tersedia di
ghc
rilis berikutnya .sumber
FamilyD
tidak mendukung default jenis sinonim terkait . Anda mungkin tidak menggunakannya, tetapi solusi lengkap mungkin memerlukan perubahan API.