返回顶部

收藏

用Scala简单地为Erlang实现maybe Monad

更多

用parsing库简单地实现一下maybe语法,也就玩玩,代码质量神马的别吐槽。不知道maybe是什么?简单来说就是替换掉嵌套过深的case。

Main

import scala.util.parsing.combinator.syntactical.StandardTokenParsers

object MonadMain extends App{

  val sou = Maybem{
    """
      maybe do {
        BB <- (f1, A, B);;
        CC <- (f1, 2, BB);;
        DD <- (f1, BB, (f2, CC, BB));;
        EE <- (f2, DD, 10)
      }
    """
  }
  import MaybemOutput._
  println(output(parse(sou.get)))
}

Maybem

trait MayBe
case class Option(left: MayBe, right: MayBe) extends MayBe
case class Expr(oper: MayBe, args: List[MayBe]) extends MayBe
case class Fun(x: String) extends MayBe
case class Arg(value: MayBe) extends MayBe
case class Tup(values: List[String]) extends MayBe {
  override def toString = values.mkString("{", ", ", "}")
}
case class Var(x: String) extends MayBe {
  override def toString = x
}

object Maybem extends ErlangTokenParser {
  lexical.delimiters += ("{", "}", "(", ")", ";;", ",", "<-")
  lexical.reserved += ("maybe", "do", "return")

  def maybe: Parser[List[MayBe]] =
    "maybe" ~ opt("do") ~ "{" ~> repsep(option, ";;") <~ "}"

  def option: Parser[MayBe] =
    left ~ "<-" ~ right ^^ { case left ~ "<-" ~ right => Option(left, right) }

  def left: Parser[MayBe] = (
      ident ^^ {Var}
//    | "{" ~> repsep(ident, ",") <~ "}" ^^ Tup
  )

  def right: Parser[MayBe] =
    "(" ~ fun ~ "," ~ args ~ ")" ^^ {
      case "(" ~ fun ~ "," ~ args ~")" => Expr(fun, args)
    }

  def fun: Parser[MayBe] = ident ^^ Fun | right

  def args: Parser[List[MayBe]] = repsep(ident ^^ Var |numericLit ^^ Var | right, ",")

  def apply(source: String) = {
    val tokens = new lexical.Scanner(source)
    phrase(maybe)(tokens)
  }
}

object MaybemOutput {

  def parse(list: List[MayBe]): List[(String,String)] = list match {
    case Option(left: MayBe, right: MayBe) :: l1 =>
      (left.toString -> parseExpr(right)) :: parse(l1)
    case Nil =>
      Nil
  }

  def parseExpr(expr: MayBe): String = expr match {
    case Expr(func: Fun, args: List[MayBe]) =>
      func.x + parseArgs(args).mkString("(", ",", ")")
    case _ =>
      ""
  }

  def parseArgs(args: List[MayBe], s: List[String] = Nil): List[String] = args match {
    case (v: Var)::args1 =>
      parseArgs(args1, v.x::s)
    case (e: Expr)::args1 =>
      parseArgs(args1, parseExpr(e)::s)
    case Nil =>
      s.reverse
  }

  def output(parsed: List[(String,String)]): String = {
    def outputinner(parsed: List[(String,String)], just: String, res: List[String]): List[String] =  parsed match {
      case (l: String, r: String)::parsed1 =>
        outputinner(parsed1, l, "fun(" + just + ") -> bind(" + r :: res)
      case Nil =>
        ("fun(" + just + ") -> return(" + just + ") end" :: res).reverse
    }
    outputinner(parsed, "", Nil).mkString("", ", ", ") end"*parsed.length+"().")
  }

}

标签:scala,erlang

收藏

0人收藏

支持

0

反对

0

发表评论