2012-04-04 3 views
4

준 인용문은 컴파일하는 동안 AST 코드를 생성 할 수 있지만 준 인용문이 작성된 위치에 생성 된 코드를 삽입합니다. 컴파일시 생성 된 코드를 어떤 식 으로든 삽입 할 수 있습니까? 예를 들어 QQ가 작성된 모듈 파일과 다른 특정 모듈 파일의 경우? 하드 코딩 된 모듈 구조에 따라 다르지만 괜찮습니다.Haskell에서 컴파일하는 동안 다른 위치에 코드를 포함시키는 방법은 무엇입니까?

QQ에서는 불가능하지만 누구나 다른 방법을 알고 있다면 제안을받을 수 있습니다.

+4

나는 이것이 당신이 달성하고자하는 것을 언급 할 수 있다면 도움이 될 것이라고 생각합니다. 기술적으로 TH는 컴파일되는 모듈을 읽고 파싱하는 것을 포함하여 임의의 IO를 실행할 수 있으므로 다른 곳이나 다른 모듈에서 물건을 가져올 수 있지만 세부 사항은 수행하려는 작업에 따라 다릅니다. – hammar

답변

4

이렇게 대답하려면 유사 인용 부호가 무엇인지 알아두면 도움이됩니다. GHC Documentation에서 준 quoter가

data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp, 
           quotePat :: String -> Q Pat, 
           quoteType :: String -> Q Type, 
           quoteDec :: String -> Q [Dec] } 

의 값, 그것은 표현의 템플릿 하스켈 표현 인 하나 ExpQ 이상, PatQ, TypeQDecQ에 임의의 문자열에서 파서이다 , 패턴, 유형 및 선언을 각각 나타냅니다.

준 인용문을 사용하는 경우 GHC는 파서를 문자열에 적용하여 ExpQ (또는 다른 유형)을 만든 다음 결과 템플릿 haskell 표현식을 연결하여 실제 값을 생성합니다.

TH 식에 액세스 할 수 있도록 쿼시 코드 구문 분석과 스플 라이스를 분리하는 것이 좋습니다. 그런 다음 해당 표현식을 다른 모듈로 가져 와서 직접 연결할 수 있습니다.

유사 인용 부호의 유형을 알면, 이것이 가능하다는 것이 쉽게 알 수 있습니다. 일반적으로 당신은 TH 표현을 얻을 파서를 직접 추출하고 나중에 스플 라이스 수, 대신

-- file Expr.hs 
eval :: Expr -> Integer 
expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat } 

-- file Foo.hs 
import Expr 
myInt = eval [expr|1 + 2|] 

으로 QQ를 사용 : 물론

-- file Foo.hs 
import Expr 

-- run the QQ parser 
myInt_TH :: ExpQ 
myInt_TH = quoteExp expr "1 + 2" 

-- file Bar.hs 
import Foo.hs 

-- run the TH splice 
myInt = $(myInt_TH) 

을 당신이 자신을 모든이를 작성하는 경우, 당신은 quasi-quotes를 건너 뛰고 파서와 Template Haskell을 직접 사용할 수 있습니다. 어느 쪽이든 꽤 똑같습니다.