Created
October 23, 2023 17:34
QueryParam.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package zio.http | |
import zio.ZIO | |
sealed trait QueryParam[+A] { self => | |
def flatMap[B](f: A => QueryParam[B]):QueryParam[B] = QueryParam.FlatMap(self, f) | |
def map[B](f: A => B):QueryParam[B] = self.flatMap(a => QueryParam.succeed(f(a))) | |
def zipWith[B, C](that: => QueryParam[B])(f: (A, B) => C):QueryParam[C] = | |
for { | |
a <- self | |
b <- that | |
} yield f(a, b) | |
def <*>[B](that: => QueryParam[B]):QueryParam[(A, B)] = self.zip(that) | |
def zip[B](that: => QueryParam[B]):QueryParam[(A, B)] = self.zipWith(that)((a, b) => a -> b) | |
def zipString(name:String):QueryParam[(A, String)] = QueryParam.zipAll(self, QueryParam.string(name)) | |
def zipInt(name:String):QueryParam[(A, Int)] = QueryParam.zipAll(self, QueryParam.int(name)) | |
def run(request: Request):Either[String, A] = QueryParam.run(self, request) | |
def runZIO(request: Request): ZIO[Any, String, A] = QueryParam.runZIO(self, request) | |
} | |
object QueryParam { | |
private case class Succeed[A](value:A) extends QueryParam[A] | |
private case class Attempt[A](name:String, f: String => Either[String, A]) extends QueryParam[A] | |
private case class Fail(message:String) extends QueryParam[Nothing] | |
private case class FlatMap[A, B](self: QueryParam[A], f: A => QueryParam[B]) extends QueryParam[B] | |
private def succeed[A](value:A):QueryParam[A] = Succeed(value) | |
def attempt[A](name:String, f: String => Either[String, A]):QueryParam[A] = Attempt(name, f) | |
def string(name:String):QueryParam[String] = attempt(name, in => Right(in)) | |
def fromEither[A](e: Either[String, A]): QueryParam[A] = e match { | |
case Left(value) => fail(value) | |
case Right(value) => succeed(value) | |
} | |
def zipAll[A, B](a: QueryParam[A], b: QueryParam[B]): QueryParam[(A, B)] = | |
a.zipWith(b) { case (a, b) => (a, b)} | |
def zipAllWith[A, B, C](a: QueryParam[A], b: QueryParam[B])(f: (A, B) => C): QueryParam[C] = | |
a.zipWith(b) { case (a, b) => f(a, b)} | |
def zipAll[A, B, C](a: QueryParam[A], b: QueryParam[B], c: QueryParam[C]):QueryParam[(A, B, C)] = { | |
zipAll(a, b).zip(c).map { case ((a, b), c) => (a, b, c) } | |
} | |
def zipAllWith[A, B, C, D](a: QueryParam[A], b: QueryParam[B], c: QueryParam[C])(f: (A, B, C) => D): QueryParam[D] = { | |
zipAll(a, b).zipWith(c) { case ((a, b), c) => f(a, b, c) } | |
} | |
def fail(message:String):QueryParam[Nothing] = Fail(message) | |
def int(name:String):QueryParam[Int] = | |
string(name).flatMap(in => fromEither(in.toIntOption.toRight(s"not an int: $in"))) | |
def run[A](self:QueryParam[A], request: Request):Either[String, A] = { | |
self match { | |
case Succeed(value) => Right(value) | |
case Fail(value) => Left(value) | |
case FlatMap(self, f) => | |
run(self, request) match { | |
case Left(value) => Left(value) | |
case Right(value) => | |
run(f(value), request) | |
} | |
} | |
} | |
def runZIO[A](self: QueryParam[A], request: Request): ZIO[Any, String, A] = | |
ZIO.from(run(self, request)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Would result in an API like: