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

この問題は、template-haskellパッケージのバージョン2.9.0.0を持つGHC 7.8.3に存在します。これは、template-haskellパッケージのバージョン2.7.0.0を持つGHC 7.4.2にも存在していました。(GHC 7.6。*については確認しませんでしたが、そこにも存在していたと思います。)GHCのすべてのバージョン(「これはGHCバージョンVでのみ修正されました」を含む)の解決策に興味があります。


2
見たreifyInstances
クワルツ2015

2
@Kwarrtz:私は今それを試しました。ただし、機能しません。それはちょうど同じに上昇与えInstanceDIのこぎりのようにS reifyputStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])と評価され[InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]、型族インスタンスを欠いています。
Antal Spector-Zabusky 2015

1
reify必要な情報が返されないのは不思議です。おそらくshowいくつかの情報を隠していますか?Infoオブジェクトを直接調べてみましたか?
クワルツ2015

@Kwarrtz:InfoShowインスタンスは単なる派生であり、の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
@アベル:私たちは激しい合意にあると思います–あなたの元のコメントは素晴らしいアイデアを引き付けるには十分ではなかったと言いましたが、それユラスの答えを引き付けました!私は良い答えが何であるかについて完全に同意します:-)
Antal Spector-Zabusky

回答:


15

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

奇妙なことに、THは独自のASTを使用しますが、これは内部コンパイラのASTに準拠していません。その結果、THを介して新しい機能(たとえば、関連付けられたタイプファミリー)が自動的に利用できなくなります。チケットを開いて実装しなければならない人もいます。

参考:内部reifyClass関数関連する型ファミリーを無視します(これはによって返されるタプルの5番目の要素classExtraBigSigですClassATItem。の定義も参照してください)。

技術的には、関連する型ファミリーのサポートをに実装するのは簡単ですreifyが、おそらくASTが関連する型のデフォルトをサポートしていないように思われるため、TH APIに下位互換性のない変更が必要になる可能性があります。

追加:現在実装されており(APIの変更なし)、次のghcリリースで使用できるようになる可能性があります。


1
@ AntalS-Zつまり、関連する型の同義語のデフォルトFamilyDはサポートされていません。おそらくそれらを使用していませんが、完全なソリューションではAPIの変更が必要になる場合があります。
Yuras

5
@アベル、賞金を最後まで開いたままにしておくことも、良い回答が投票を獲得するのに役立つ傾向があるため、迅速に落札するよりも良い回答に報酬を与えるためのより効果的な方法です。
dfeuer

1
バウンティ期間が終了しました。バグレポート#10891が解決されるまで、または解決されない限りこれが最良の(そして唯一の)回答です。おそらく、回答にバグレポートへのリンクを含めることをお勧めします。
Abel

1
ちなみに、#10891は修正されており、マージされるのを待っています。
シナン

1
@SwiftsNamesake AFAIK ghc開発者は、TH APIを壊すことなく内部ASTを自由に変更したいと考えています。おそらく他の理由もあるでしょう。
Yuras 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.