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

scala – 将Monad包装成解析器 – 我是否需要Monad变换器以及如

发布时间:2020-12-16 18:12:02 所属栏目:安全 来源:网络整理
导读:我有一个monadic类型的Exp,我想构建一个解析为这样一个值的解析器.以下代码有效,但是我能做些更好/更酷的事情吗? def grid(x: Int,y: Int): Problem = ???def expInt: Parser[Exp[Int]] = ???def grid: Parser[Exp[Problem]] = for{ ex ~ _ ~ ey - "grid("
我有一个monadic类型的Exp,我想构建一个解析为这样一个值的解析器.以下代码有效,但是我能做些更好/更酷的事情吗?

def grid(x: Int,y: Int): Problem = ???
def expInt: Parser[Exp[Int]] = ???

def grid: Parser[Exp[Problem]] =
  for{
    ex ~ _ ~ ey <- "grid(" ~> expInt ~ "," ~ expInt <~ ")"
  } yield for{
    x <- ex
    y <- ey
  } yield grid(x,y)

我听说过monad变形金刚,但仍然有点害怕Scalaz 7的奇怪的导入系统.有人可以回答是否

>我可以使用monad变换器和
>原则上看起来如何,使用Scalaz 7作为包装我自己的Exp Monad的Scala组合器解析器.

解决方法

首先是简单的部分 – “怪异”的导入系统:

import scalaz._,Scalaz._

就这样.这将永远有效(当然,除非是名称冲突,但这对任何库来说都是可能的并且易于解决),没有人会因为没有使用新的单点菜单导入而瞧不起你,这主要是关于文档的.

monad变换器的基本模式是你有一个WhateverT [F [_],…]类型类,它有一个名为runWhateverT(或只是run)的方法返回一个F [Whatever […]].

在这种情况下,看起来你想要最终得到一个Parser [Exp],这表明你需要自己的ExpT [F [_]]变换器.我不会从有关如何实现它的细节开始(当然,这取决于你的monad的语义),但是将使用Scalaz的OptionT给出一个例子:

import scala.util.parsing.combinator._
import scalaz._,Scalaz._

object MyParser extends RegexParsers {
  implicit val monad = parserMonad(this)

  def oddNumber: OptionT[Parser,Int] = OptionT.optionT(
    "d+".r ^^ (_.toInt) ^^ (i => (i % 2 != 0) option i)
  )

  def pairOfOdds: OptionT[Parser,(Int,Int)] = for {
    _ <- literal("(").liftM[OptionT]
    x <- oddNumber
    _ <- literal(",").liftM[OptionT]
    y <- oddNumber
    _ <- literal(")").liftM[OptionT]
  } yield (x,y)

  def apply(s: String) = parse(pairOfOdds.run,s)
}

有关我们为什么需要隐式val monad = …行的讨论,请参见my question here.

它的工作原理如下:

scala> MyParser("(13,43)")
res0: MyParser.ParseResult[Option[(Int,Int)]] = [1.9] parsed: Some((13,43))

scala> MyParser("(13,42)")
res1: MyParser.ParseResult[Option[(Int,Int)]] = [1.8] parsed: None

请注意,oddNumber.run会给我们一个Parser [Option [Int]],它将解析一串数字并返回Some(i)(如果它们代表奇数)或None(如果它们是偶数).

我们实际上并没有打算调用oddNumber.run,但是,在这种情况下 – 我们使用monad变换器的事实意味着我们可以用一个提升的Parser动作(这里的文字(…))组成oddNumber单身理解.

这里的语法是丑陋的 – 例如,我们失去了很好的?组合器和从String到Parser [String]的隐式转换,但是如果我们想要的话,我们可以很容易地编写这些东西的提升版本.

(编辑:李大同)

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

    推荐文章
      热点阅读