プログラミングhaskell 8章 version scala 〜前半〜

  type Parser[T] = StateT[Option, String, T]

  def pure[T](x: T): Parser[T] =
    StateT.pure[Option, String, T](x)

  def failure: Parser[String] =
    StateT[Option, String, String](_ => None)

  def item: Parser[String] =
    StateT{
      case "" => None
      case xs => Some(xs.tail, xs.head.toString)
    }

  implicit class ParserOps[T](p: Parser[T]) {
    def +++(q: Parser[T]): Parser[T] =
      StateT[Option, String, T] { inp =>
        p.run(inp) orElse q.run(inp)
      }
  }
  println((item +++ pure("d")).run("abc"))
  println((failure +++ pure("d")).run("abc"))
  println((failure +++ failure).run("abc"))

  def item2 = for {
    s1 <- item
    _  <- item
    s2 <- item
  } yield s1 + s2
  println(item2.run("abcd"))

  def sat(p: String => Boolean): Parser[String] =
    for {
      x <- item
      r <- if (p(x)) pure(x) else failure
    } yield r
  def digit = sat(_.matches("^\\d$"))
  def lower = sat(_.matches("^[a-z]$"))
  def upper = sat(_.matches("^[A-Z]$"))
  def letter = sat(_.matches("^[a-zA-Z]$"))
  def alphanum = sat(_.matches("^[0-9a-zA-Z]$"))
  def char(x: String) = sat(_ == x)

  println(sat(x => x.matches("^1$")).run("22"))

  def string(str: String): Parser[String] = str match {
    case "" => pure("")
    case _ => for {
      x  <- char(str.head.toString)
      xs <- string(str.tail.mkString)
    } yield x + xs
  }

  println(string("abc").run("abcdef"))

  def many[T](p: Parser[T]): Parser[List[T]] = many1(p) +++ pure(Nil)
  def many1[T](p: Parser[T]): Parser[List[T]] =
    for {
      v  <- p
      vs <- many(p)
    } yield v :: vs

  println(many(digit).run("123abc"))
  println(many(digit).run("abcdef"))

  def ident: Parser[String] =
    for {
      x  <- lower
      xs <- many(alphanum)
    } yield x + xs.mkString

  def nat: Parser[Int] =
    many1(digit).map(_.mkString.toInt)

  def space: Parser[String] =
    for {
      _ <- many(sat(_ == " "))
      r <- pure("")
    } yield r

  println(nat.run("123abc"))
  println(space.run("   abc"))