2016-10-10 14 views
7

나는 두 가지 해석이 가능한 문법 라이브러리를 만들고있다 : 1) 문법에 따라 문자열 파싱 2) 문법에 정의 된 언어로 문자열 생성.Scala + Cats에서 Free Monads로 임의의 나무 사용하기

라이브러리는 고양이를 사용하여 문법의 AST를 무료 모나드로 만듭니다. 그러나 무료 모나드는 AST의 목록과 같은 표현을 생성하기 때문에 성립되지 않을 수도 있지만 문법은 문 목록과는 거리가 멀며 임의의 나무 구조에 훨씬 가깝습니다.

~ 연산자를 사용하여 연결된 2 개의 문법을 나타내는 것으로 트리를 구현할 수있었습니다. AST는 그 자체로 임의의 AST 인 문법 목록입니다.

제 질문은 : 무료 모나드에서 AST의 하위 트리를 재귀하는 좋은 방법은 무엇입니까?

내 현재 구현 is here:

def parserInterpreter: GrammarA ~> ParserInterpreterState = 
new (GrammarA ~> ParserInterpreterState) { 
    def apply[A](fa: GrammarA[A]): ParserInterpreterState[A] = 
    fa match { 
     case Regx(regexp) => parseRegex(regexp) 
     case Optional(b) => parseOptional(b.foldMap(this)) 
     case m @ Multi(g) => 
     def x: State[String, A] = 
      State.apply(state => { 
      g.foldMap(this) 
       .run(state) 
       .map { 
       case (s, ParseSuccess(_)) => x.run(s).value 
       case r @ (s, ParseFailure()) => (s, ParseSuccess(s).asInstanceOf[A]) 
       } 
       .value 
      }) 
     x 
     case Choice(a, b) => 
     State.apply(state => { 
      val runA = a.foldMap(this).run(state).value 
      if (runA._2.asInstanceOf[ParseResult[_]].isSuccess) 
      runA 
      else { 
      b.foldMap(this).run(state).value 
      } 
     }) 
    } 
} 

주 특히 Multi 경우 재귀 서브 트리를 해석하기 위해 안전 재귀 (즉 꼬리없는 재귀)를 사용하는 것이다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

Please click here for the source code.

답변

0

당신이 파서/예쁜 프린터 라이브러리를 구축하는 경우, 당신은 조작 된 개체는 아마 모나드 수 없습니다. 고양이의 InvariantMonoidal (무료 제공 자, FreeInvariantMonoidal)을 대신 사용할 수 있습니다. 관련 자습서에는 흥미로운 코덱이 a section 있습니다.