Отримання асоційованих типів синонімів із шаблоном Haskell


257

Чи може Шаблон 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 пакета шаблон-haskell; він також був присутній у GHC 7.4.2 з версією 2.7.0.0 пакета шаблон-haskell. (Я не перевіряв GHC 7.6. *, Але, думаю, він там також був присутній.) Мене цікавлять рішення для будь-якої версії GHC (включаючи "це було виправлено лише у GHC версії V ").


2
Ви подивилися reifyInstances?
Kwarrtz

2
@Kwarrtz: Я просто спробував це зараз. Однак це не працює; це просто породжує те саме, InstanceDщо я бачив із reify: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])оцінює [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []], якому бракує екземплярів сімейства типів.
Antal Spector-Zabusky

1
Я вважаю дивним, що reifyне повертає потрібної інформації. Можливо show, ховається якась інформація? Ви намагалися дослідити Infoоб'єкт безпосередньо?
Kwarrtz

@Kwarrtz: Боюся Info, що 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). Я згоден, це дивно; саме тому я задав це питання :-)
Antal Spector-Zabusky

1
@Abel: Я думаю , що ми в сильному угоді - оригінал коментар сказав , що це не було достатньо , щоб залучити блискучу ідею, але це дійсно залучить відповідь Юрась в! Я абсолютно згоден у тому, що хороша відповідь :-)
Антал Спектор-Забуський

Відповіді:


15

Він не реалізований, тому що його ніхто не вимагав.

Дивно, що TH використовує власний AST, який не відповідає AST внутрішнього компілятора. Як результат, будь-яка нова функція (наприклад, асоційовані родини типів) не є автоматично доступною через TH. Хтось повинен відкрити квиток і реалізувати його.

Для довідки: внутрішня reifyClassфункція ігнорує сім'ї асоційованих типів (це 5-й елемент кортежу, повернутий classExtraBigSig, див. Також визначення ClassATItem.)

Технічно це має бути легко реалізувати підтримку сімейства асоційованих типів у reify, але, швидше за все, це потребуватиме невідповідних змін у API API, наприклад, тому що його AST, здається, не підтримує параметри за замовчуванням пов'язаних типів.

Додано: Зараз він реалізований (без зміни API-коду btw) і, ймовірно, буде доступний у наступному ghcвипуску.


1
@ AntalS-Z Я маю на увазі, що FamilyDне підтримує типові синоніми асоційованого типу . Ви, ймовірно, не використовуєте їх, але повне рішення може вимагати зміни API.
Юрас

5
@Abel, залишаючи баунті відкритим до кінця, також, як правило, допомагають хороші відповіді залучати голоси, тож це більш ефективний спосіб нагородити хорошу відповідь, ніж присудити її швидко.
dfeuer

1
Термін щедрості закінчився Це найкраща (і єдина) відповідь, поки не буде вирішено звіт про помилку №10891 . Можливо, гарна ідея включити у свою відповідь посилання на повідомлення про помилку.
Авель

1
FYI, №10891 виправлено, і він чекає об’єднання.
Сінан

1
@SwiftsNamesake AFAIK ghc розробники хочуть вільно змінювати внутрішній AST, не порушуючи TH API. Напевно, є й інші причини.
Юрас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.