[英]Using arbitrary trees with Free Monads in Scala+Cats
我正在為語法創建一個庫,該庫將有兩種不同的解釋:1)基於語法分析字符串2)生成語法定義的語言中的字符串。
該庫使用貓來創建免費的monad語法的AST。 但是,這似乎並不完美,因為免費的monad會創建我的AST的列表形式表示形式,這對語句列表非常有用,但是語法離語句列表很遠,並且更接近於任意樹結構。
我設法通過使用~
運算符來表示2個語法,以實現我的樹。 AST然后是本身就是任意AST的語法列表。
我的問題是:什么是在免費monad中遞歸AST的子樹的好方法?
我當前的實現在這里:
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
案例使用了不安全的遞歸(即不是尾遞歸)來遞歸地解釋子樹。 有一個更好的方法嗎?
如果要構建解析器/漂亮打印機庫,則要處理的對象可能不是monad。 您可能想使用貓的InvariantMonoidal
(它是免費的,免費的, FreeInvariantMonoidal
)。 相關的教程中有關於編解碼器的部分 ,您可能會覺得很有趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.