2012-04-21 3 views
10

encoding 패키지의 빌드 스크립트 (Setup.hs)에 HaXml이 사용됩니다. HaXml-1.19와 HaXml-1.22 사이에서 변경된 인터페이스 비트를 사용합니다. 인코딩 패키지가 두 버전으로 빌드 할 수 있다면 좋을 것입니다. 나는Setup.hs의 빌드 방식 변경

{-# LANGUAGE CPP #-} 
#if MIN_VERSION_HaXml(1,22,0) 
-- HaXml-1.22 code 
#else 
-- HaXml-1.19 code 
#endif 

같은 일을하고, 즉, 보통의 음모 트릭을 사용하여 시도 ...하지만 패키지가 구성되기 전에 마법을 정의가 존재하지 수 있으며,이 파일은 구성 단계가 가능하도록 건설되고있다. 내 옵션은 무엇입니까? cabal-install이 Setup.hs을 컴파일하도록 호출하는 명령을 변경하는 방법이 있습니까? 왜곡을 회피하는 코드를 조건부로 선택하는 또 다른 메커니즘이 있습니까?

+0

가 얼마나 심각한 인터페이스 변화가있다 (이 아이디어는 무엇 maybeReify 및 다른 유용한 유틸리티를 포함하는의 notcpp package을 개발하기 위해 저를 인도된다)? 어떤 변화가 있습니까? 템플릿 haskell이 무엇인지에 따라 당신을 구출 할 수도 있습니다. –

+0

@benmachine 유일하게 진짜 변화는'Element' 생성자가 이제'data QName = N String | '문자열'대신에 '뭔가를 말하지 말아요'라고 말하면됩니다. 'Setup.hs' 파일은'Element' 생성자를 함수 (항상 리터럴'String'과 함께)와 패턴 매칭 (때때로 리터럴'String'과 때로는 catch-all 가변 패턴으로)으로 사용합니다. –

+0

'toQName'과'fromQName' 함수가 있다면'QName'이 존재할 때'toQName = N'과'fromQName'은'Ns'를'Just s' (그리고 다른 것은'Nothing '), 반면에'QName'이 존재하지 않으면'toQName = id'와'fromQName = Just'입니까? 그러면 뷰 패턴으로 원하는 것을 할 수있을 것입니다. 나는'toQName'과'fromQName'이 템플릿 haskell로 정의 될 수 있다고 생각합니다. 내 [notcpp 패키지] (http://hackage.haskell.org/package/notcpp) –

답변

4

인터페이스는 존재할 수도 있고 존재하지 않을 수도있는 유형의 값을 구성하고 해체 할 수 있습니다 (약!). 불행하게도, HaXml은 타입에 대해 Data 인스턴스를 가지고 있지 않으며 존재하지 않을 수도있는 타입을 참조 할 수 없기 때문에이를 정의 할 수 없으므로 Template Haskell에 의지해야합니다.

다음 모듈 수출 qnameCompat가 : 템플릿 하스켈을 사용하여 최상위 수준에 접합 할 때 N이있는 경우

{-# LANGUAGE TemplateHaskell #-} 
module HaXmlCompat (qnameCompat) where 

import Language.Haskell.TH 

qnameCompat :: Q [Dec] 
qnameCompat = do 
    mi <- maybeReify "N" 
    case mi of 
    Nothing -> sequence [ 
     tySynD (mkName "QName") [] [t| String |], 
     valD [p| toQName |] (normalB [| id |]) [], 
     valD [p| fromQName |] (normalB [| Just |]) []] 
    Just (DataConI n _ _ _) -> do 
     s <- newName "s" 
     sequence [ 
     valD [p| toQName |] (normalB (conE n)) [], 
     funD (mkName "fromQName") [ 
      clause [conP n [varP s]] (normalB (appE [| Just |] (varE s))) [], 
      clause [ [p| _ |] ] (normalB [| Nothing |]) []]] 
    Just i -> fail $ 
     "N exists, but isn't the sort of thing I expected: " ++ show i 

maybeReify :: String -> Q (Maybe Info) 
maybeReify = recover (return Nothing) . fmap Just . reify . mkName 

, qnameCompat가 확인합니다. 그렇지 않은 경우

toQName = N 
fromQName (N s) = Just s 
fromQName _ = Nothing 

, 다음이 생성됩니다 : 이제

type QName = String 
toQName = id 
fromQName = Just 

만들고 Element의를 해체 할 수 있습니다, 예를 들어, 만약 그렇다면, 다음과 같은 코드를 생성 ViewPatterns 확장을 사용 :

myElt :: String -> Element i 
myElt = Elem (toQName "elemName") [] [] 

eltName :: Element i -> String 
eltName (Elem (fromQName -> Just n) _ _) = n 

ViewPatterns하는 것은 물론, 필수 편리하지만되지 않습니다 : 그냥 잘 작동합니다 fromQName의 결과에 대한 일반적인 패턴 매칭을 사용.

+0

위대한보세요. –

2

가 가장 좋은 건 버전 테스트를 수행 한 다음 한 번 실제 Setup.hs에 핸드 오프 그루터기 Setup.hs 파일을 생성 할 수 있도록 Setup.hs의 컴파일을 제어 cabal-install/Distribution/Client/SetupWrapper.hs 매우 많은 노브로하지 않는 것 버전이 무엇인지 알아 냈습니다.

다른 트릭은 설치 스크립트에서 사용하는 호환 shim 라이브러리를 만드는 것입니다.이 shim 라이브러리에는 적절한 버전 트릭이 있습니다.

어쩌면 진짜 질문은 이것입니다 : Setup.hs 외부 라이브러리를 사용하는 이유는 무엇입니까?

+0

흠과 비슷한 아이디어를 사용하여 어떻게 도움을 줄 것인가? ? 아직 나에게 건네주는 것을 (둘 다) 구축하려고 시도하지 않습니까? –

+0

맞습니다. 적절한 매크로 정의로 GHC를 다시 호출해야합니다. –

관련 문제