了解scalaz中的免费monad

时间:2018-02-26 16:20:20

标签: scala scalaz free-monad

我正在Free中尝试使用Scalaz monad并尝试构建简单的解释器来解析和评估表达式,如:

dec(inc(dec(dec(10)))

其中dec表示递减,inc表示递增。这是我得到的:

trait Interpreter[A]
case class V[A](a: A) extends Interpreter[A]

object Inc {
  private[this] final val pattern = Pattern.compile("^inc\\((.*)\\)$")
  def unapply(arg: String): Option[String] = {
    val m = pattern.matcher(arg)
    if(m.find()){
      Some(m.group(1))
    } else None
  }
}

object Dec {
  private[this] final val pattern = Pattern.compile("^dec\\((.*)\\)$")
  def unapply(arg: String): Option[String] = {
    val m = pattern.matcher(arg)
    if(m.find()){
      Some(m.group(1))
    } else None
  }
}

object Val {
  def unapply(arg: String): Option[Int] =
    if(arg.matches("^[0-9]+$")) Some(Integer.valueOf(arg))
    else None
}

现在我需要构建AST。目前看来如下:

def buildAst(expression: String): Free[Interpreter, Int] = 
   expression match {
     case Inc(arg) => inc(buildAst(arg))
     case Dec(arg) => dec(buildAst(arg))
     case Val(arg) => value(arg)
}

private def inc(i: Free[Interpreter, Int]) = i.map(_ + 1)
private def dec(d: Free[Interpreter, Int]) = d.map(_ - 1)
private def value(v: Int): Free[Interpreter, Int] = Free.liftF(V(v))

现在测试应用程序时:

object Test extends App{

  val expression = "inc(dec(inc(inc(inc(dec(10))))))"

  val naturalTransform = new (Interpreter ~> Id) {
    override def apply[A](fa: Interpreter[A]): Id[A] = fa match {
      case V(a) => a
    }
  }

  println(buildAst(expression).foldMap(naturalTransform)) //prints 12
}

它的效果非常好(我不确定它是否属于scalaz样式)。

问题 是提取器对象IncDecVal感觉就像样板代码。有没有办法减少这种代码重复。

如果支持的功能数量变大,这肯定会成为一个问题。

0 个答案:

没有答案