Bắt các từ đồng nghĩa loại liên quan với mẫu Haskell


257

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 reifysẽ 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ì InstanceDkhô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 reifykhô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 ").


2
Bạn đã nhìn reifyInstanceschưa
Kwarrtz

2
@Kwarrtz: Tôi vừa mới thử nó. Nó không hoạt động, mặc dù; nó chỉ làm phát sinh các InstanceDs 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.
Antal Spector-Zabusky

1
Tôi thấy thật kỳ lạ khi reifykhông trả lại thông tin cần thiết. Có lẽ showlà ẩn một số thông tin? Bạn đã thử kiểm tra Infođối tượng trực tiếp?
Kwarrtz

@Kwarrtz: Tôi sợ Info's Showdụ được chỉ là xuất phát một, và tương tự cho các Showví 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 :-)
Antal Spector-Zabusky

1
@ Tin: Tôi nghĩ rằng chúng tôi đang thỏa thuận bạo lực - nhận xét ban đầu của bạn nói rằng nó không đủ để thu hút một ý tưởng tuyệt vời, nhưng nó đã thu hút câu trả lời của Yuras! Tôi hoàn toàn đồng ý về câu trả lời hay là gì :-)
Antal Spector-Zabusky

Câu trả lời:


15

Nó không được thực hiện bởi vì không ai yêu cầu nó.

Điều kỳ lạ là TH sử dụng AST của chính nó, không tuân theo AST của trình biên dịch nội bộ. Do đó, mọi tính năng mới (ví dụ: các loại gia đình được liên kết) sẽ không tự động có sẵn thông qua TH. Một số người phải mở một vé và thực hiện nó.

Đối với tham chiếu: reifyClasshàm bên trong bỏ qua các họ kiểu liên quan (nó là phần tử thứ 5 của bộ dữ liệu được trả về bởi classExtraBigSig, xem thêm định nghĩa của ClassATItem.)

Về mặt kỹ thuật, có thể dễ dàng thực hiện hỗ trợ gia đình loại liên quan reify, nhưng rất có thể nó sẽ yêu cầu các thay đổi không tương thích ngược trong TH API, ví dụ vì AST của nó dường như không hỗ trợ mặc định loại liên quan.

Đã thêm: Hiện đã được triển khai (không có thay đổi API btw) và có thể sẽ có sẵn trong ghcphiên bản tiếp theo .


1
@ AntalS-Z Ý tôi là FamilyDkhông hỗ trợ mặc định từ đồng nghĩa loại liên quan . Bạn có thể không sử dụng chúng, nhưng giải pháp đầy đủ có thể yêu cầu thay đổi API.
Yura

5
@Abel, để tiền thưởng mở cho đến cuối cùng cũng có xu hướng giúp câu trả lời tốt thu hút phiếu bầu, vì vậy đó là cách hiệu quả hơn để thưởng cho một câu trả lời tốt hơn là trao giải nhanh chóng.
dfeuer

1
Thời hạn tiền thưởng đã hết hạn. Đây là câu trả lời tốt nhất (và duy nhất), cho đến khi hoặc trừ khi báo cáo lỗi # 10891 được giải quyết . Có lẽ một ý tưởng tốt để bao gồm một liên kết đến báo cáo lỗi trong câu trả lời của bạn.
Abel

1
FYI, # 10891 đã được sửa và nó đang chờ để được hợp nhất.
sinan

1
@SwiftsNamesake Các nhà phát triển AFAIK ghc muốn thay đổi AST nội bộ một cách tự do mà không phá vỡ API TH. Có lẽ có những lý do khác nữa.
Yura
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.