2013-05-07 2 views
4

하스켈 표현식을 감안할 때, 나는 알파 변환을 수행하고 싶습니다. 일부 비어 있지 않은 변수의 이름을 바꿉니다.하스켈 식으로의 알파 변환

haskell-src-exts Exp 트리에서 작동하는 내 자신의 기능을 구현하기 시작했습니다. 그러나 놀라 울 정도로 치명적이지는 않지만 궁금증을 풀 수 없습니다. 이런 종류의 소스 변환을위한 사용하기 쉬운 라이브러리 솔루션? 이상적으로는 haskell-src-exts와 통합되어야합니다.

+0

[bound] (https://github.com/ekmett/bound/) 라이브러리가 ekmett에게 도움이 될 수 있습니다. –

답변

5

"일반 게시판 스크랩"스타일의 제네릭 라이브러리가 빛나는 문제 중 하나입니다!

제가 가장 익숙한 사람은 the uniplate package입니다. 그러나 실제로는 설치하지 않았으므로 the lens package에있는 (매우 유사한) 기능을 사용하겠습니다. 여기서 아이디어는 Data.Data.Data (가장 적합한 수식 이름 임) 및 관련 클래스를 사용하여 다형성 방식으로 일반 작업을 수행한다는 것입니다.

alphaConvert :: Module -> Module 
alphaConvert = template %~ changeName 

changeName :: Name -> Name 
changeName (Ident n) = Ident $ n ++ "_conv" 
changeName n = n 

(%~) 연산자 lens 내지 단지 일반 순회 template 의해 선택된 모든 행 changeName 함수를 적용하는 것을 의미한다 :

여기서 가장 간단한 예이다. 그래서 이것은 모든 영숫자 식별자를 찾아서 그것에 _conv을 붙이는 것입니다. 이 식별자 외부 범위에 정의 된 (예 : 수입 된 것으로) 로컬 바인딩과 구분하지 않기 때문에

module AlphaConv where 
import Language.Haskell.Exts 
import Control.Lens 
import Control.Lens.Plated 
import Data.Data.Lens 

instance Plated_conv Module_conv 
main_conv 
    = do ParseOk_conv md_conv <- parseFile_conv "AlphaConv.hs" 
     putStrLn_conv $ prettyPrint_conv md_conv 
     let md'_conv = alphaConvert_conv md_conv 
     putStrLn_conv $ prettyPrint_conv md'_conv 

alphaConvert_conv :: Module_conv -> Module_conv 
alphaConvert_conv = template_conv %~ changeName_conv 

changeName_conv :: Name_conv -> Name_conv 
changeName_conv (Ident_conv n_conv) 
    = Ident_conv $ n_conv ++ "_conv" 
changeName_conv n_conv = n_conv 

정말 유용하지,하지만 기본적인 아이디어를 보여줍니다 자체 소스에서이 프로그램을 실행하면이 생산 .

lens 약간 위협적으로 보일 수 있습니다 (이 기능보다 훨씬 많은 기능이 있음). uniplate 또는 다른 라이브러리를 더 쉽게 찾을 수 있습니다.

실제 문제에 접근하는 방법은 내부적으로 알파로 변환 할 하위 표현식을 먼저 선택한 다음 변환을 사용하여 변경하려는 이름을 수정하는 다중 부분 변환입니다.

+2

제네릭이 가능한 한 가지 문제 (AST 사용)는 해결하지만 다른 것은 아니며 (알파 등가물, 회피 등). 나는이 문제를 후자에 대해 더 많은 것으로 해석했다.이 라이브러리에는 몇 가지 라이브러리 ('언 바운드','바인딩')가 있지만'haskell-src-exts'에 쉽게 적용 할 수 있는지 모르겠습니다. –

+0

+1 멋진 글에 대한, 그러나, 나는 이것이 내가 무엇을 찾고 있는지 확실하지 않습니다. 나는 당신이 언급 한 라이브러리에 익숙하지 않지만, 필자가 피하려고하는 것은 그렇게 많은 상용구가 아니라 진정한 논리이다. – xcvii