]> gitweb @ CieloNegro.org - task-reporter.git/commitdiff
monadic tsv
authorPHO <pho@cielonegro.org>
Fri, 10 Oct 2014 07:18:58 +0000 (16:18 +0900)
committerPHO <pho@cielonegro.org>
Fri, 10 Oct 2014 07:18:58 +0000 (16:18 +0900)
build.sbt
src/main/scala/jp/ymir/taskReporter/core/TSV.scala

index 922e0eeeeedbe74cdc6aafb554871ac1e73f90fd..e6692d372dc677028c9be6aae19e8b7348adab68 100644 (file)
--- 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 <http://toedter.com/jcalendar/>
index 28d9833ad828817d390ac2dacff1eae45edde8ea..fc4947d766cecc33a2601d4cebd6a2b6cb97056c 100644 (file)
@@ -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(_))