Skip to content

Commit

Permalink
Issue davegurnell#1: Applicative zip. Check returns whenever the same…
Browse files Browse the repository at this point in the history
… value is returned. and uses zip now.
  • Loading branch information
rpiaggio committed Aug 19, 2018
1 parent 6fc77fd commit de7dbb2
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,30 @@ import monocle._
import scala.language.experimental.macros
import scala.language.higherKinds

trait Rule1Syntax {
trait CheckSyntax {

implicit class AnyRuleOps[A](value: A) {
def validate[F[_] : Applicative](implicit rule: Rule[F, A, A]): F[Checked[A]] =
rule(value)
}

implicit def fieldPartialToRule[F[_], G[_], R[_], A, B](self: Rule1Ops[F, A]#FieldPartial[B])(implicit rule: Rule[G, B, B], canLift: CanLift[Applicative, F, G, R], evG: Applicative[G]): Rule[R, A, A] = {
implicit def fieldPartialToRule[F[_], G[_], R[_], A, B](self: CheckOps[F, A]#FieldPartial[B])(implicit rule: Check[G, B], canLift: CanLift[Applicative, F, G, R], evG: Applicative[G]): Rule[R, A, A] = {
self.apply
}

implicit class Rule1Ops[F[_] : Applicative, A](self: Check[F, A]) {
def and[G[_] : Applicative, R[_]](that: Check[G, A])(implicit canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] = {
implicit val evApplicativeR: Applicative[R] = canLift.evR
implicit class CheckOps[F[_] : Applicative, A](self: Check[F, A]) {
def and[G[_] : Applicative, R[_]](that: Check[G, A])(implicit canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
(self zip that).map(_._1) // Unless we define different semantics for Check, this seems to be the best we can do.
// Well, we could also check for equality at runtime and throw an exception or warning, but it doesn't seem like the right thing to do.

(self.liftWith(canLift.liftF), that.liftWith(canLift.liftG)).mapN((x, _) => x)
}

def field[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(rule: Rule[G, B, B])(implicit canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def field[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(rule: Check[G, B])(implicit canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
self and rule.at(path, lens)

def field[G[_] : Applicative, R[_], B](accessor: A => B)(rule: Rule[G, B, B])(implicit canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def field[G[_] : Applicative, R[_], B](accessor: A => B)(rule: Check[G, B])(implicit canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
macro RuleMacros.field[F, G, R, A, B]

class FieldPartial[B](path: Path, lens: Lens[A, B]) {
def apply[G[_], R[_]](implicit rule: Rule[G, B, B], canLift: CanLift[Applicative, F, G, R], evG: Applicative[G]): Rule[R, A, A] =
def apply[G[_], R[_]](implicit rule: Check[G, B], canLift: CanLift[Applicative, F, G, R], evG: Applicative[G]): Check[R, A] =
field(path, lens)(rule)
}

Expand All @@ -52,16 +50,16 @@ trait Rule1Syntax {

// This approach is a bit better, but still the compiler requests that we explicit the
// A type in the accessor, which is not very elegant (see ReadmeSpec line 34)
def fieldWith[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(builder: A => Rule[G, B, B])(implicit canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def fieldWith[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(builder: A => Check[G, B])(implicit canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
self and Rule.pure(value => builder(value).at(path, lens).apply(value))

def fieldWith[G[_] : Applicative, R[_], B](accessor: A => B)(builder: A => Rule[G, B, B])(implicit canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def fieldWith[G[_] : Applicative, R[_], B](accessor: A => B)(builder: A => Check[G, B])(implicit canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
macro RuleMacros.fieldWith[F, G, R, A, B]

def fieldWithImplicit[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(implicit builder: A => Rule[G, B, B], canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def fieldWithImplicit[G[_] : Applicative, R[_], B](path: Path, lens: Lens[A, B])(implicit builder: A => Check[G, B], canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
fieldWith(path, lens)(builder)

def fieldWithImplicit[G[_] : Applicative, R[_], B](accessor: A => B)(implicit builder: A => Rule[G, B, B], canLift: CanLift[Applicative, F, G, R]): Rule[R, A, A] =
def fieldWithImplicit[G[_] : Applicative, R[_], B](accessor: A => B)(implicit builder: A => Check[G, B], canLift: CanLift[Applicative, F, G, R]): Check[R, A] =
macro RuleMacros.fieldWithImplicit[F, G, R, A, B]
}

Expand Down
Loading

0 comments on commit de7dbb2

Please sign in to comment.