Haskell şablonu ile ilişkili tür eş anlamlılarını alma


257

Template Haskell, bir tür sınıfında bildirilen ilişkili tür eş anlamlılarının adlarını ve / veya bildirimlerini bulabilir mi? İstediğimi reifyyapmayı bekliyordum , ancak gerekli tüm bilgileri sağlamıyor gibi görünüyor. İşlev tipi imzaları almak için çalışır:

% 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)))])
       []

Ancak, sınıfa ilişkilendirilmiş bir tür eşanlamlısı eklemek çıktıda hiçbir değişikliğe (yeniden adlandırmaya kadar) neden olmaz:

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)))])
       []

Adını biliyorsanız, Fbunun hakkında bilgi arayabilirim:

Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
                 Ghci3.F
                 [PlainTV a_1627405973]
                 (Just StarT))
        []

Ama Filk etapta adını bulamıyorum . Type sınıfının bir örneğini eklesem bile InstanceD, tanımı hakkında hiçbir bilgi yoktur:

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)))
                  []]

Eğer reifyiş olmaz, bir geçici çözüm elle ilişkilendirmek tip eş anlamlılarını listeleme dışında var mı?

Bu sorun, şablon haskell paketinin 2.9.0.0 sürümü ile GHC 7.8.3'te bulunmaktadır; GHC 7.4.2'de template-haskell paketinin 2.7.0.0 sürümü ile mevcuttu. (GHC 7.6. * 'Da kontrol etmedim, ama orada da var olduğunu hayal ediyorum.) GHC'nin herhangi bir sürümü için çözümlerle ilgileniyorum ("bu sadece GHC V sürümünde düzeltildi " dahil).


2
Baktın mı reifyInstances?
Kwarrtz

2
@Kwarrtz: Şimdi denedim. Yine de çalışmıyor; sadece InstanceDgördüğümle aynı şeyleri doğurur reify: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])değerlendirir [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []], tip aile örneklerinden yoksundur.
Antal Spector-Zabusky

1
reifyGerekli bilgileri döndürmeyen garip buluyorum . Belki de showbazı bilgiler saklanıyor? InfoNesneyi doğrudan incelemeyi denediniz mi?
Kwarrtz

@Kwarrtz: Korkarım Info'in Showörnek sadece bir türetilmiştir ve aynı Show-örneğin Dec. Eğer istedi ve Ancak, ben de doğrudan kontrol edebilirsiniz, no: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")üretir just a SigD- ki gerçekten tek şey [Dec]içinde ClassD! (gerektirir LambdaCase). Bunun garip olduğunu kabul ediyorum; bu yüzden bu soruyu sordum :-)
Antal Spector-Zabusky

1
@Abel: - Orijinal yorum o parlak bir fikir çekmek için yeterli olmadığını söyledi, ama ben şiddet hemfikiriz düşünüyorum did Yuras cevabını çekmek! İyi bir cevabın ne olduğu konusunda kesinlikle katılıyorum :-)
Antal Spector-Zabusky

Yanıtlar:


15

Uygulanmadı çünkü kimse talep etmedi.

Garip olan şey, TH'nin dahili derleyicinin AST'sini takip etmeyen kendi AST'sini kullanmasıdır. Sonuç olarak, TH aracılığıyla yeni bir özellik (örneğin ilişkili tür aileleri) otomatik olarak kullanılamaz. Bazıları bir bilet açmalı ve uygulamalıdır.

Referans için: dahili reifyClassfonksiyon ilişkili tip ailelerini yok sayar (döndürülen grubun 5. elemanıdır, classExtraBigSigayrıca bkz ClassATItem. Tanımı) .

Teknik olarak ilişkili tip aile desteğini uygulamak kolay olmalıdır reify, ancak büyük olasılıkla TH API'de geriye dönük uyumsuz değişiklikler gerektirecektir, çünkü AST'si ilişkili tip varsayılanlarını desteklemiyor gibi görünmektedir.

Eklendi: Şimdi uygulandı (API değişikliği btw olmadan) ve muhtemelen bir sonraki ghcsürümde mevcut olacak .


1
@ AntalS-Z Yani ilişkili tür eşanlamlı varsayılanlarınıFamilyD desteklemiyor . Muhtemelen bunları kullanmıyorsunuz, ancak tam çözüm API değişikliği gerektirebilir.
Yuras

5
@Abel, ödülün sonuna kadar açık bırakılması da iyi cevapların oy vermesine yardımcı olma eğilimindedir, bu yüzden iyi bir cevabı hızlı bir şekilde ödüllendirmekten daha ödüllendirmenin daha etkili bir yoludur.
dfeuer

1
Ödül süresi doldu. Bu, # 10891 hata raporu çözülene kadar (ve yalnızca) en iyi yanıttır . Cevabınıza hata raporu bağlantısı eklemek için iyi bir fikir olabilir.
Abel

1
Bilginize, # 10891 düzeltildi ve birleştirilmeyi bekliyor.
sinan

1
AFAIK ghc geliştiricileri, TH API'yi bozmadan dahili AST'yi serbestçe değiştirmek istiyor. Muhtemelen başka sebepler de vardır.
Yuras
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.