]> gitweb @ CieloNegro.org - task-reporter.git/blob - src/main/scala/jp/ymir/taskReporter/core/TSV.scala
5b2d261f5cec1bf49e97a0a303d95b69efcb7301
[task-reporter.git] / src / main / scala / jp / ymir / taskReporter / core / TSV.scala
1 package jp.ymir.taskReporter.core
2 import scala.collection._
3 import scala.collection.immutable.StringLike
4 import scala.language.higherKinds
5 import scala.language.implicitConversions
6 import scala.language.reflectiveCalls
7 import scalaz._
8 import Scalaz._
9
10 object TSV {
11   type Header = Seq[Symbol]
12   type Field  = String
13   type Record = Map[Symbol, Field]
14
15   // ---
16   type Failure[   F[_], R] = String => F[R]
17   type Success[A, F[_], R] = A      => F[R]
18
19   trait Parser[A] {
20     def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
21   }
22
23   implicit def ParserFunctor = new Functor[Parser] {
24     def map[A, B](m: Parser[A])(f: A => B) = new Parser[B] {
25       def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
26         def ks_(a: A) = ks(f(a))
27         return m.runParser(kf, ks_)
28       }
29     }
30   }
31
32   implicit def ParserApplicative = new Applicative[Parser] {
33     def point[A](a: => A) = new Parser[A] {
34       def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
35         = ks(a)
36     }
37     def ap[A, B](m: => Parser[A])(fm: => Parser[A => B]) = new Parser[B] {
38       def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
39         def ks_(f: A => B): F[R] = {
40           def ks__(a: A) = ks(f(a))
41           return m.runParser(kf, ks__)
42         }
43         return fm.runParser(kf, ks_)
44       }
45     }
46   }
47
48   implicit def ParserMonad = new Monad[Parser] {
49     def point[A](a: => A) = a.point[Parser]
50
51     def bind[A, B](m: Parser[A])(f: A => Parser[B]) = new Parser[B] {
52       def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
53         def ks_(a: A) = f(a).runParser(kf, ks)
54         return m.runParser(kf, ks_)
55       }
56     }
57   }
58
59   implicit def ParserMonadError = new MonadError[({type λ[String, α] = Parser[α]})#λ, String] {
60     def point[A](a: => A) = a.point[Parser]
61     def bind[A, B](m: Parser[A])(f: A => Parser[B]) = m.flatMap(f)
62
63     def handleError[A](m: Parser[A])(f: String => Parser[A]) = new Parser[A] {
64       def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = {
65         def kf_(e: String) = f(e).runParser(kf, ks)
66         return m.runParser(kf_, ks)
67       }
68     }
69
70     def raiseError[A](e: String) = new Parser[A] {
71       def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
72         = kf(e)
73     }
74   }
75   implicit def ToMonadErrorIdOps(e: String) = new {
76     def raiseError[A]: Parser[A]
77       = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].raiseError(e)
78   }
79
80   def runParser[A](p: Parser[A]): Either[String, A] = {
81     type F[R] = Either[String, R]
82     def left (e: String): F[A] = Left(e)
83     def right(x: A     ): F[A] = Right(x)
84     return p.runParser(left, right)
85   }
86   // ---
87
88   def decode[A: FromRecord](tsv: StringLike[_]): Seq[A] = {
89     val lines  = tsv.split('\n').filter(!_.isEmpty)
90     val header = lines.head.split('\t').map(Symbol(_))
91     val body   = lines.tail.map(line => (header zip line.split('\t')).toMap)
92     return body.map(implicitly[FromRecord[A]].parseRecord)
93   }
94
95   trait FromRecord[A] {
96     def parseRecord(r: Record): A
97   }
98
99   trait FromField[A] {
100     def parseField(f: Field): Parser[A]
101   }
102   implicit def toFromFieldOps(f: Field) = new {
103     def parseField[A: FromField]
104       = implicitly[FromField[A]].parseField(f)
105   }
106
107   trait ToRecord[A] {
108     def toRecord(a: A): Record
109   }
110
111   trait ToField[A] {
112     def toField(a: A): Field
113   }
114
115   // Option[A]
116   implicit def OptionFromField[A: FromField] = new FromField[Option[A]] {
117     def parseField(f: Field): Parser[Option[A]] = {
118       if (f.isEmpty) {
119         return (None : Option[A]).point[Parser]
120       }
121       else {
122         f.parseField[A].map { Some(_) }
123       }
124     }
125   }
126
127   // String
128   implicit def StringFromField = new FromField[String] {
129     def parseField(f: Field): Parser[String] = f.point[Parser]
130   }
131
132   // Int
133   implicit def IntFromField = new FromField[Int] {
134     def parseField(f: Field): Parser[Int] = {
135       try {
136         f.toInt.point[Parser]
137       }
138       catch {
139         case e: NumberFormatException =>
140           e.getMessage().raiseError[Int]
141       }
142     }
143   }
144 }