From 1b5b7ced1ab2585580ab8f1b65dcf4f4fe21bff2 Mon Sep 17 00:00:00 2001 From: PHO Date: Fri, 10 Oct 2014 16:18:58 +0900 Subject: [PATCH] monadic tsv --- build.sbt | 3 ++ .../scala/jp/ymir/taskReporter/core/TSV.scala | 54 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/build.sbt b/build.sbt index 922e0ee..e6692d3 100644 --- a/build.sbt +++ b/build.sbt @@ -8,6 +8,9 @@ libraryDependencies <+= libraryDependencies += "org.scala-tools.sbinary" %% "sbinary" % "0.4.2" +libraryDependencies += + "org.scalaz" %% "scalaz-core" % "7.1.0" + // There is also manual dependencies in ./lib: // // - JCalendar diff --git a/src/main/scala/jp/ymir/taskReporter/core/TSV.scala b/src/main/scala/jp/ymir/taskReporter/core/TSV.scala index 28d9833..fc4947d 100644 --- a/src/main/scala/jp/ymir/taskReporter/core/TSV.scala +++ b/src/main/scala/jp/ymir/taskReporter/core/TSV.scala @@ -1,12 +1,66 @@ package jp.ymir.taskReporter.core import scala.collection._ import scala.collection.immutable.StringLike +import scala.language.higherKinds +import scalaz._ object TSV { type Header = Seq[Symbol] type Field = String type Record = Map[Symbol, Field] + // --- + type Failure[ F[_], R] = String => F[R] + type Success[A, F[_], R] = A => F[R] + + trait Parser[A] { + def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] + } + + implicit def ParserFunctor = new Functor[Parser] { + def map[A, B](m: Parser[A])(f: A => B) = new Parser[B] { + def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { + def ks_(a: A) = ks(f(a)) + return m.runParser(kf, ks_) + } + } + } + + implicit def ParserApplicative = new Applicative[Parser] { + def point[A](a: => A) = new Parser[A] { + def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = ks(a) + } + + def ap[A, B](m: => Parser[A])(fm: => Parser[A => B]) = new Parser[B] { + def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { + def ks_(f: A => B): F[R] = { + def ks__(a: A) = ks(f(a)) + return m.runParser(kf, ks__) + } + return fm.runParser(kf, ks_) + } + } + } + + implicit def ParserMonad = new Monad[Parser] { + def point[A](a: => A) = implicitly[Applicative[Parser]].point(a) + + def bind[A, B](m: Parser[A])(f: A => Parser[B]) = new Parser[B] { + def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { + def ks_(a: A) = f(a).runParser(kf, ks) + return m.runParser(kf, ks_) + } + } + } + + def runParser[A](p: Parser[A]): Either[String, A] = { + type F[A] = Either[String, A] + def left (errMsg: String): F[A] = Left(errMsg) + def right(x : A ): F[A] = Right(x) + return p.runParser(left, right) + } + // --- + def decode[A: FromRecord](tsv: StringLike[_]): Seq[A] = { val lines = tsv.split('\n').filter(!_.isEmpty) val header = lines.head.split('\t').map(Symbol(_)) -- 2.40.0