Skip to content

Instantly share code, notes, and snippets.

@stanch
Last active November 17, 2015 11:09
Show Gist options
  • Save stanch/9042312 to your computer and use it in GitHub Desktop.
Save stanch/9042312 to your computer and use it in GitHub Desktop.
import scala.language.higherKinds
import play.api.libs.functional._
import shapeless._
import shapeless.ops.hlist.RightFolder
import play.api.data.mapping.{ From, Reader, Rule }
import play.api.libs.json.{Json, JsValue}
import play.api.data.mapping.json.Rules._
object applicativeFolder2 extends Poly2 {
// Rule[I, X] :: Rule[I, L] -> Rule[I, X :: L]
implicit def caseApp[A, B <: HList, I, F[_, _]](implicit app: Applicative[({ type λ[O] = F[I, O] })#λ]) =
at[F[I, A], F[I, B]] { (a, b) ⇒
app.apply[A, A :: B](app.map[B, A ⇒ A :: B](b, x ⇒ y ⇒ y :: x), a)
}
// X :: Rule[I, L] -> Rule[I, X :: L]
// uses ruleApplicative[I].pure
implicit def casePure[A, B <: HList, I, F[_, _]](implicit app: Applicative[({ type λ[O] = F[I, O] })#λ], pure: A <:!< F[_, _]) =
at[A, F[I, B]] { (a, b) ⇒
app.apply[A, A :: B](app.map[B, A ⇒ A :: B](b, x ⇒ y ⇒ y :: x), app.pure(a))
}
}
// Rule[I, X] :: Rule[I, Y] :: ... :: HNil -> Rule[I, X :: Y :: ... :: HNil]
def liftRule[I] = new RuleLifter[I]
class RuleLifter[I] {
val app = Rule.applicativeRule[I]
def apply[L <: HList](l: L)(implicit folder: RightFolder[L, Rule[I, HNil], applicativeFolder2.type]) =
l.foldRight(app.pure(HNil: HNil))(applicativeFolder2)
}
// (Reader[I] ⇒ Rule[I, X] :: Rule[I, Y] :: ... :: HNil) -> Rule[I, X :: Y :: ... :: HNil]
def from[I] = new FromMaker[I]
class FromMaker[I] {
def apply[L <: HList, O](l: Reader[I] ⇒ L)(implicit folder: RightFolder.Aux[L, Rule[I, HNil], applicativeFolder2.type, Rule[I, O]]) =
From[I](__ ⇒ liftRule[I](l(__)))
}
// a wild case class appears
case class A(foo: Int, bar: Int, baz: Int)
val r = from[JsValue] { __ ⇒
(__ \ "foo").read[Int] ::
(__ \ "bar").read[Int] ::
3 :: // turns into Rule(_ ⇒ Success(3))
HNil
}.fmap(Generic[A].from) // hurray, Rule[JsValue, A]!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment