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
's 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
?