加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala Cats中使用带有Free Monads的任意树

发布时间:2020-12-16 08:51:21 所属栏目:安全 来源:网络整理
导读:我正在为语法创建一个库,它有两种不同的解释:1)根据语法解析字符串2)用语法定义的语言生成字符串. 该库使用cat来创建语法的AST作为免费monad.然而,似乎它可能不是完美的契合,因为自由monad创建了我的AST的列表式表示,这对于语句列表很好,但是语法远离语句列
我正在为语法创建一个库,它有两种不同的解释:1)根据语法解析字符串2)用语法定义的语言生成字符串.

该库使用cat来创建语法的AST作为免费monad.然而,似乎它可能不是完美的契合,因为自由monad创建了我的AST的列表式表示,这对于语句列表很好,但是语法远离语句列表并且更接近任意树结构.

我设法通过使用?运算符来表示连接的2个语法来实现我的树.然后,AST是一个语法列表,它们本身就是任意的AST.

我的问题是:在免费monad中递归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 case使用不安全的递归(即不是尾递归)以便递归地解释子树.有一个更好的方法吗?

Please click here for the source code.

解决方法

如果要构建Parser / Pretty打印机库,则正在操作的对象可能不是monad.你可能想要使用猫的InvariantMonoidal(和它的免费conterpart,FreeInvariantMonoidal).关于编解码器的相关教程有 a section,您可能会感兴趣.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读