プログラミングhaskell 9章 version scala 〜後半〜

val box: List[String] =
  List(
    "+---------------+",
    "|               |",
    "+---+---+---+---+",
    "| q | c | d | = |",
    "+---+---+---+---+",
    "| 1 | 2 | 3 | + |",
    "+---+---+---+---+",
    "| 4 | 5 | 6 | - |",
    "+---+---+---+---+",
    "| 7 | 8 | 9 | * |",
    "+---+---+---+---+"
  )

val buttons: String = {
  val standard = "qcd=123+456-789*0()/"
  val extra = "QCD \033\010\014\n"
  standard + extra
}

val showbox: IO[Unit] = seqn((1 to 13).zip(box).map(t => writeat((1, t._1))(t._2)).toList)

def display(s: String): IO[Unit] =
  for {
    _ <- writeat((3, 2))("             ")
    _ <- writeat((3, 2))(s.toCharArray.takeRight(13).mkString)
  } yield ()

def calc(s: String): IO[Unit] =
  for {
    _ <- display(s)
    c <- getChar
    _ <- if (buttons.contains(c)) process(c)(s)
    else for {
      _ <- beep
      _ <- calc(s)
    } yield ()
  } yield ()

def process(c: Char)(s: String): IO[Unit] = s match {
  case _ if "qQ\033".contains(c) => quit
  case _ if "dD\010\014".contains(c) => delete(s)
  case _ if "=\n".contains(c) => eval(s)
  case _ if "cC".contains(c) => clear
  case _ => process(c)(s)
}

def quit = goto((1, 14))
def delete(s: String) = s match {
  case "" => calc("")
  case xs => calc(xs.head.toString)
}
import ParserMain._
def eval(s: String): IO[Unit] =  expr.run(s) match {
  case Some((_, n)) => calc(n.toString)
  case None =>
    for {
      _ <- beep
      _ <- calc(s)
    } yield ()
}
def clear: IO[Unit] = calc("")
def press(c: Char)(s: String): IO[Unit] = calc(s + c.toString)

val run: IO[Unit] =
  for {
    _ <- cls
    _ <- showbox
    _ <- clear
  } yield ()
run.unsafeRunSync()