템플릿 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에서 template-haskell 패키지 버전 2.9.0.0과 함께 나타납니다. 또한 template-haskell 패키지의 버전 2.7.0.0과 함께 GHC 7.4.2에 존재했습니다. (GHC 7.6. *는 확인하지 않았지만, 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 5

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는 : - 원래 댓글이 기발한 생각을 유치하는 것만으로는 충분하지했다, 그러나 나는 우리가 폭력 계약에 있다고 생각 했다 Yuras의 답변을 유치! 나는 좋은 대답이 무엇인지에 절대적으로 동의한다 :-)
— Antal Spector-Zabusky

답변:


15

아무도 요청하지 않았기 때문에 구현되지 않았습니다.

이상한 점은 TH가 자체 컴파일러를 사용하지 않는 자체 AST를 사용한다는 것입니다. 결과적으로 TH를 통해 새로운 기능 (예 : 관련 유형 군)을 자동으로 사용할 수 없습니다. 일부는 티켓을 열고 구현해야합니다.

참조 : 내부 reifyClass함수 는 연관된 유형 패밀리를 무시합니다 (에서 반환되는 튜플의 다섯 번째 요소 classExtraBigSig입니다 ClassATItem.의 정의도 참조하십시오 ).

기술적으로는 관련 유형 군 지원을 쉽게 구현할 수 reify있지만, AST가 관련 유형 기본값을 지원하지 않는 것처럼 보이기 때문에 TH API에서 이전 버전과 호환되지 않는 변경이 필요할 것입니다.

추가됨 : 이제 API 변경 (btw)없이 구현 되었으며 다음 ghc릴리스 에서 제공 될 예정입니다.


1
@ AntalS-Z 관련 형식 동의어 기본값을FamilyD 지원하지 않습니다 . 아마도 그것들을 사용하고 있지 않지만 전체 솔루션을 사용하려면 API 변경이 필요할 수 있습니다.
— Yuras

5
@Abel, 현상금을 끝까지 열어두면 좋은 답변이 투표를 유도하는 데 도움이되는 경향이 있으므로, 좋은 답변을 신속하게 수여하는 것보다 좋은 답변을 보상하는 더 효과적인 방법입니다.
— dfeuer

1
바운티 기간이 만료되었습니다. 이것은 버그 보고서 # 10891이 해결 될 때까지 또는 그렇지 않은 경우에 가장 적합한 유일한 답변 입니다. 아마도 답변에 버그 보고서에 대한 링크를 포함시키는 것이 좋습니다.
— Abel

1
참고로, # 10891은 고정되어 병합 대기 중입니다.
— sinan

1
@SwiftsNamesake AFAIK ghc 개발자는 TH API를 중단하지 않고 내부 AST를 자유롭게 변경하려고합니다. 아마도 다른 이유도있을 것입니다.
— Yuras
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.