2014-10-06 1 views
3

하스켈에서 컴파일러를 작성하는 중첩 된 데이터 형식으로 작업하는 동안 특정 문제가 여러 번 발생했습니다. 대서양 표준시에 대한 몇 가지 변환을 수행하는 동안 나는추가 데이터로 하스켈에서 중첩 된 ADT 주석 달기

data AST = AST [GlobalDecl] 

data GlobalDecl = Func Type Identifier [Stmt] | ... 

data Stmt = Assign Identifier Exp | ... 

data Exp = Var Identifier | ... 

같은 ADT 정의 뭔가를해야합니다, 나는 간단히 표현에 사용되는 변수 일부 추가 데이터를 다니기 할 수 있습니다. 지금까지 고려한이 작업을 수행하는 모든 옵션은 상당히 어색한 것으로 보입니다. 나는 새로운 데이터 유형 만들 수 :

data Exp' = Var' Identifier ExtraInfo | ... 

을하지만 내가 새로운 정의가 필요 의미 Stmt', GDecl'는 형성하기 위해 약간 AST'을 변경했습니다. 이렇게하면

data Exp = Var Identifier | Var' Identifier ExtraInfo | ... 

에서, typechecker가 더 이상 실수에 Var'를 사용하지 못할 수 있습니다 : 또 다른 옵션은 원래 Exp에 다른 데이터 생성자를 추가,하지만 프로그램의 특정 부분을 사용하는 것입니다 다른 일부는 프로그램입니다. 세 번째 옵션은 단순히 프로그램의 나머지 부분에 아무런 관련성이 없다하더라도, 모든 시간의 주위에 여분의 정보를 유지하는 것입니다 :

data Exp = Var Identifier ExtraInfo | ... 

이 가능 하죠,하지만 당신은 여분을 필요로하는 경우 특히 추한 정보를 간략하게. 당분간 나는 여분의 정보를 Map Indentifier ExtraInfo에 넣고, 명시 적으로 또는 모나드를 통해 AST과 함께 전달했습니다. 예를 들어, 동일한 Identifier의 다른 출현에 다른 정보로 주석을 추가해야하는 경우이 작업은 매우 어려울 수 있습니다.

누구나 중첩 된 데이터 유형에 주석을 달 수있는 세련된 기술이 있습니까? 이처럼, 당신의 모든 유형이 더 다형성 한 경우

+0

아마도'데이터 Exp a = 변수 식별자 a | ... '? 그런 다음 주석을 통과시킬 수는 있지만 실제로 사용하지 않는 함수는'a'에서 다형성을 갖습니다. 주석을 처리 할 수없는 함수는'Exp()'를 사용하고,'Exp() '유형의 함수를 주석으로 추가합니다. -> Exp ExtraInfo', 추가 정보가 필요한 변환은'Exp ExtraInfo'를 사용합니다. 기본적으로 "항상 유지"옵션이지만 형식 검사기를 사용하면 사용중인 단계를 적용 할 수 있습니다. – Ben

답변

2

:

data AST a = AST a 
data GlobalDecl t i s = Func t i [s] | ... 
data Stmt i e = Assign i e | ... 
data Exp a = Var a | ... 

당신은 일시적으로 튜플로를 인스턴스화 할 수 있습니다 - 예를 들어, Exp (Int, Identifier) - 중간 계산의 경우. 필요에 따라 편의상 위의 구체적인 유형에 대해 newtype을 입력 할 수 있습니다.

3

추가 데이터로 구조에 태그를 지정하는 옵션 중 하나는 더 높은 유형의 유형 매개 변수를 사용하는 것입니다. 변수에 태그를 지정해야하는 경우 예를 들어 다음과 같이 할 수 있습니다.

data AST f = AST [GlobalDecl f] 
data GlobalDecl f = Func Type Identifier [Stmt f] | ... 
data Stmt = Assign Identifier (Exp f) | ... 
data Exp f = Var (f Identifier) | ... 

이 베드로가 제안한 것과 유사한 대신 그것은 단지 당신이 변화 할 부분 parametricizes 완전히 일반적인 유형을 만드는 것입니다.

당신은 AST Identity와 원래, 태그가 지정되지 않은 구조를 얻을 수 있습니다 또는 Var (ExtraInfo, Identifier)Var (f Identifier)을 설정 할 AST ((,) ExtraInfo) 같은 유형을 가질 수 있습니다. 당신은 몇 가지 추가 정보 (예 : 토큰 위치)와 AST의 모든 수준에 태그를해야하는 경우 지금

data AST f = AST [f (GlobalDecl f)] 
data GlobalDecl f = Func (f (Type f)) (f (Identifier f)) [f (Stmt f)] | ... 
data Stmt f = Assign (f (Identifier f)) (f (Exp f)) | ... 
data Exp f = Var (f (Identifier f)) | ... 

AST ((,) ExtraInfo) 매 분기 지점에서 추가 정보를 포함하는 것처럼

, 당신도 데이터 유형을 정의 할 수 있습니다 구문 트리 (부여, 위의 구조와 함께 일하는 조금 성 가시고 얻을 것이다).

+0

흠 ... 이것은 가능합니다. 당신이 말했듯이, 그것은 빠르게 어색하게 될 것입니다. 나는 그것이 어떤 함수가 증강 된 타입을 받아 들일 수 있도록 강제 할 수있게 해주는 것을 좋아한다. –