Skip to content

Instantly share code, notes, and snippets.

@blouerat
Created April 29, 2015 11:56
Show Gist options
  • Save blouerat/935c161a2fcb3aa9f190 to your computer and use it in GitHub Desktop.
Save blouerat/935c161a2fcb3aa9f190 to your computer and use it in GitHub Desktop.
Monad, Applicative & Json 2
object jsonExample {
import scala.language.higherKinds
import scalaz._, Scalaz._
type Path = String
type JValue
type JObject
implicit class RichDisjunction[A, B](disjunction: A \/ B) {
def nel: NonEmptyList[A] \/ B = disjunction.leftMap(NonEmptyList(_))
}
implicit class RichTraverse[F[_], A](fa: F[A]) {
def traverseV[B: Semigroup, C](f: A => Validation[B, C])(implicit tf: Traverse[F]): B \/ F[C] = tf.traverseU(fa)(f).disjunction
}
sealed trait JsonError
case class ParsingError(input: String) extends JsonError
case class MissingFieldError(path: Path) extends JsonError
case class ExtractionError[A](input: String) extends JsonError
type JsonErrors = NonEmptyList[JsonError]
trait JsonRead[A] {
def read(value: JValue): JsonErrors \/ A
}
implicit val JObjectRead = new JsonRead[JObject] {
def read(value: JValue): JsonErrors \/ JObject = ???
}
implicit val ListRead = new JsonRead[List[JValue]] {
def read(value: JValue): JsonErrors \/ List[JValue] = ???
}
def parse(input: String): ParsingError \/ JValue = ???
def field(jObject: JObject, path: Path): MissingFieldError \/ JValue = ???
def read[A](value: JValue)(implicit reader: JsonRead[A]): JsonErrors \/ A = reader.read(value)
def readV[A](value: JValue)(implicit reader: JsonRead[A]): Validation[JsonErrors, A] = read[A](value).validation
case class Result(meta: JObject, body: List[JObject])
def run(input: String): JsonErrors \/ Result =
for {
json <- parse(input).nel
jObject <- read[JObject](json)
result <- {
val meta = field(jObject, "meta").nel.flatMap(read[JObject])
val body = for {
jObject <- field(jObject, "body").nel
jValues <- read[List[JValue]](jObject)
jObjects <- jValues.traverseV(readV[JObject])
} yield jObjects
val result = (meta.validation |@| body.validation)(Result)
result.disjunction
}
} yield result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment