2013-01-08 3 views
2

그냥 하스켈 템플릿을 배우기 시작하고 스플 라이스와 관련된 간단한 문제에 매달 렸습니다. 내가 가지고있는 메인 모듈에서
템플릿 문제 Haskell 무대 제한

tupleN :: Lift a => a -> Int -> Q Exp 
tupleN a n = do 
    (TupE as) <- lift a 
    return $ as !! n 

:
모듈 하나에서 나는 튜플의 N 번째 요소를 응답 기능 tupleN을 구현했습니다

이 작동하는 것 같군
main :: IO() 
main = do 
    let tup = (1::Int,'a',"hello") 
    putStrLn $ show $(tupleN $tup 1) 

, 하지만 그렇지 않을 것입니다. 컴파일러 인쇄 오류 :

main :: IO() 
main = do 
    putStrLn $ show $(tupleN (1::Int,'a',"hello") 1) 

내가 처음 변종없는 무엇 : 바로 접합 식으로 튜플 설명을 넣으면

GHC stage restriction: `tup' 
    is used in a top-level splice or annotation, 
    and must be imported, not defined locally 
In the expression: tup 
In the first argument of `tupleN', namely `$tup' 
In the expression: tupleN ($tup) 1 

, 코드 작업이 될?

+0

템플릿, 런타임하지 : 당신은, 그러나, 크기 sz의 튜플의 i 요소를 얻을 수있는 기능으로 확장 스플 라이스를 정의 할 수 있습니다. 스플 라이스는 컴파일 할 때 실행할 수 있어야합니다. –

+0

@LouisWasserman 나는이 규칙에 대해 안다 : 나는 단지'tup' 변수를 스플 라이스 표현식에 넣기를 원한다. 'tup'의 타입에 대한 정보는 컴파일시에 사용 가능합니다. 그래서 여기에 캡쳐 될 수 있습니다. –

답변

5

tup을 스플 라이스로 사용하려고 시도했지만 tup은 일반적인 값입니다. 접두어로 $을 붙이지 마십시오.

또한 컴파일 오류가 발생하면 템플릿 Haskell이 컴파일 프로세스 중에 실행되기 때문에 GHC는 현재 모듈을 컴파일하기 전에 무엇을하는지 알 필요가 있습니다. 즉, 스플 라이스 표현식은 tup에 의존 할 수 없습니다. 이는 여전히 컴파일되고 있기 때문입니다. 스플 라이스 안에는 리터럴, 가져온 값 및 특수한 'name''TypeName 형식 만 사용할 수 있습니다.이 형식은 일종의 리터럴로 생각할 수 있습니다. 예를 들어 다음을 사용하여이 편집의 정보를 얻을 수 있습니다. reify하지만 컴파일 할 때만 사용할 수있는 데이터도 제공 할 수 있습니다. 사용자 입력이나 사용자 입력에서 생성 된 데이터를 전달할 수있는 함수를 원한다면 이는 불가능합니다.

간단히 말해, Template Haskell을 사용하여 원하는 작업을 정확하게 수행 할 수 없습니다. 하스켈은 컴파일시에 작동

import Control.Monad (unless) 
import Language.Haskell.TH 

tupleN :: Int -> Int -> Q Exp 
tupleN sz i = do 
    unless (i < sz) . reportError $ "tupleN: index " ++ show i 
    ++ " out of bounds for " ++ show sz ++ "-tuple" 
    lamE 
    [tupP (replicate i wildP 
     ++ [varP (mkName "x")] 
     ++ replicate (sz - i - 1) wildP)] 
    (varE (mkName "x"))