web-dev-qa-db-ja.com

テンプレートHaskellに関連付けられた型の同義語を取得する

テンプレート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が機能しない場合、関連タイプの同義語を手動でリストする以外に回避策がありますか?

この問題は、template-haskellパッケージのバージョン2.9.0.0を備えたGHC 7.8.3に存在します。 GHC 7.4.2にはtemplate-haskellパッケージのバージョン2.7.0.0が含まれていました。 (GHC 7.6。*をチェックしませんでしたが、そこにあったと思います。)GHCのすべてのバージョンのソリューションに興味があります(「これはGHCバージョンでのみ修正されました[〜#〜] v [〜#〜] ")。

254

誰も要求していないため、実装されていません。

奇妙なことに、THは独自のASTを使用しますが、これは内部コンパイラのASTに従いません。その結果、新しい機能(関連するタイプファミリなど)は、THを介して自動的に使用可能になりません。チケットを開いて実装する必要がある人もいます。

参照:内部reifyClass関数 ignores 関連付けられたタイプファミリ( classExtraBigSig によって返されるTupleの5番目の要素です。 ClassATItem 。)

技術的にはreifyに関連するタイプファミリサポートを簡単に実装できるはずですが、ほとんどの場合、TH AP​​Iには後方互換性のない変更が必要です。そのASTは関連する型のデフォルトをサポートしていないようです。

追加:現在は 実装済み (API変更なし)であり、おそらく次のghcで利用可能になるでしょうリリース。

13
Yuras