]> gitweb @ CieloNegro.org - task-reporter.git/blobdiff - src/main/scala/jp/ymir/taskReporter/core/TSV.scala
wip
[task-reporter.git] / src / main / scala / jp / ymir / taskReporter / core / TSV.scala
index fc4947d766cecc33a2601d4cebd6a2b6cb97056c..5b2d261f5cec1bf49e97a0a303d95b69efcb7301 100644 (file)
@@ -2,7 +2,10 @@ package jp.ymir.taskReporter.core
 import scala.collection._
 import scala.collection.immutable.StringLike
 import scala.language.higherKinds
+import scala.language.implicitConversions
+import scala.language.reflectiveCalls
 import scalaz._
+import Scalaz._
 
 object TSV {
   type Header = Seq[Symbol]
@@ -28,9 +31,9 @@ object TSV {
 
   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 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] = {
@@ -43,7 +46,7 @@ object TSV {
   }
 
   implicit def ParserMonad = new Monad[Parser] {
-    def point[A](a: => A) = implicitly[Applicative[Parser]].point(a)
+    def point[A](a: => A) = a.point[Parser]
 
     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] = {
@@ -53,10 +56,31 @@ object TSV {
     }
   }
 
+  implicit def ParserMonadError = new MonadError[({type λ[String, α] = Parser[α]})#λ, String] {
+    def point[A](a: => A) = a.point[Parser]
+    def bind[A, B](m: Parser[A])(f: A => Parser[B]) = m.flatMap(f)
+
+    def handleError[A](m: Parser[A])(f: String => Parser[A]) = new Parser[A] {
+      def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = {
+        def kf_(e: String) = f(e).runParser(kf, ks)
+        return m.runParser(kf_, ks)
+      }
+    }
+
+    def raiseError[A](e: String) = new Parser[A] {
+      def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
+        = kf(e)
+    }
+  }
+  implicit def ToMonadErrorIdOps(e: String) = new {
+    def raiseError[A]: Parser[A]
+      = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].raiseError(e)
+  }
+
   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)
+    type F[R] = Either[String, R]
+    def left (e: String): F[A] = Left(e)
+    def right(x: A     ): F[A] = Right(x)
     return p.runParser(left, right)
   }
   // ---
@@ -73,10 +97,12 @@ object TSV {
   }
 
   trait FromField[A] {
-    def parseField(f: Field): A
+    def parseField(f: Field): Parser[A]
+  }
+  implicit def toFromFieldOps(f: Field) = new {
+    def parseField[A: FromField]
+      = implicitly[FromField[A]].parseField(f)
   }
-  def parseField[A: FromField](f: Field): A
-    = implicitly[FromField[A]].parseField(f)
 
   trait ToRecord[A] {
     def toRecord(a: A): Record
@@ -88,23 +114,31 @@ object TSV {
 
   // Option[A]
   implicit def OptionFromField[A: FromField] = new FromField[Option[A]] {
-    def parseField(f: Field): Option[A] = {
+    def parseField(f: Field): Parser[Option[A]] = {
       if (f.isEmpty) {
-        return None
+        return (None : Option[A]).point[Parser]
       }
       else {
-        return Some(implicitly[FromField[A]].parseField(f))
+        f.parseField[A].map { Some(_) }
       }
     }
   }
 
   // String
   implicit def StringFromField = new FromField[String] {
-    def parseField(f: Field): String = f
+    def parseField(f: Field): Parser[String] = f.point[Parser]
   }
 
   // Int
   implicit def IntFromField = new FromField[Int] {
-    def parseField(f: Field): Int = f.toInt
+    def parseField(f: Field): Parser[Int] = {
+      try {
+        f.toInt.point[Parser]
+      }
+      catch {
+        case e: NumberFormatException =>
+          e.getMessage().raiseError[Int]
+      }
+    }
   }
 }