Mẫu Haskell có thể tìm ra tên và / hoặc khai báo của các từ đồng nghĩa loại liên quan được khai báo trong một lớp loại không? Tôi dự kiến reify
sẽ làm những gì tôi muốn, nhưng dường như nó không cung cấp tất cả các thông tin cần thiết. Nó hoạt động để có được chữ ký loại chức năng:
% 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)))])
[]
Tuy nhiên, việc thêm một từ đồng nghĩa loại được liên kết vào lớp sẽ không gây ra thay đổi (đổi tên) trong đầu ra:
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)))])
[]
Nếu tôi biết tên của F
, tôi có thể tra cứu thông tin về nó:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Nhưng tôi không thể tìm thấy tên của F
ở nơi đầu tiên. Ngay cả khi tôi thêm một thể hiện của lớp loại, thì InstanceD
không có thông tin nào về định nghĩa:
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)))
[]]
Nếu reify
không hoạt động, có cách giải quyết nào khác ngoài việc liệt kê các từ đồng nghĩa loại liên kết theo cách thủ công không?
Vấn đề này hiện diện trong GHC 7.8.3 với phiên bản 2.9.0.0 của gói template-haskell; nó cũng đã có mặt trong GHC 7.4.2 với phiên bản 2.7.0.0 của gói template-haskell. (Tôi đã không kiểm tra GHC 7.6. *, Nhưng tôi tưởng tượng nó cũng có mặt ở đó.) Tôi quan tâm đến các giải pháp cho bất kỳ phiên bản GHC nào (bao gồm cả "điều này chỉ được sửa trong phiên bản GHC V ").
InstanceD
s giống như tôi đã thấy với reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
đánh giá [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, mà thiếu các thể hiện gia đình kiểu.
reify
không trả lại thông tin cần thiết. Có lẽ show
là ẩn một số thông tin? Bạn đã thử kiểm tra Info
đối tượng trực tiếp?
Info
's Show
dụ được chỉ là xuất phát một, và tương tự cho các Show
ví dụ cho Dec
. Tuy nhiên, tôi cũng có thể kiểm tra trực tiếp, khi bạn hỏi, và không có: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
sản xuất just a SigD
- đó thực sự là điều duy nhất trong [Dec]
trong ClassD
! (yêu cầu LambdaCase
). Tôi đồng ý nó là lạ; đó là lý do tại sao tôi hỏi câu hỏi này :-)
reifyInstances
chưa