Skip to content

Instantly share code, notes, and snippets.

@stanch
Last active August 29, 2015 13:56
Show Gist options
  • Save stanch/9083484 to your computer and use it in GitHub Desktop.
Save stanch/9083484 to your computer and use it in GitHub Desktop.
// F[A] :: F[B] :: ... :: M :: F[N] :: O :: ... :: HNil -> F[A :: B :: ... :: M :: N :: O :: ... :: HNil]
object applicativeFolder extends Poly2 {
// (F[A], F[B]) -> F[A :: B]
implicit def caseApp[A, B <: HList, F[_]](implicit app: Applicative[F]) =
at[F[A], F[B]] { (a, b) ⇒
app.apply[A, A :: B](app.map[B, A ⇒ A :: B](b, x ⇒ y ⇒ y :: x), a)
}
// (A, F[B]) -> F[A :: B] (uses Applicative.pure)
implicit def casePure[A, B <: HList, F[_]](implicit app: Applicative[F], pure: A <:!< F[_]) =
at[A, F[B]] { (a, b) ⇒
app.apply[A, A :: B](app.map[B, A ⇒ A :: B](b, x ⇒ y ⇒ y :: x), app.pure(a))
}
}
// works:
type L[O] = Option[O]
implicit val app = play.api.libs.functional.syntax.applicativeOption
val x = RightFolder.hlistRightFolder[Int, HNil, L[HNil], applicativeFolder.type, L[HNil]]
val y = RightFolder.hlistRightFolder[Int, Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: HNil]]
val z = RightFolder.hlistRightFolder[Int, Int :: Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: Int :: HNil]]
// fails (could not find parameter `ft` in `z`):
type L[O] = Rule[JsValue, O]
implicit val ruleApplicative: Applicative[L] = Rule.applicativeRule[JsValue]
val x = RightFolder.hlistRightFolder[Int, HNil, L[HNil], applicativeFolder.type, L[HNil]]
val y = RightFolder.hlistRightFolder[Int, Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: HNil]]
val z = RightFolder.hlistRightFolder[Int, Int :: Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: Int :: HNil]]
// works:
type L[O] = Rule[JsValue, O]
implicit val ruleApplicative: Applicative[L] = Rule.applicativeRule[JsValue]
val x = RightFolder.hlistRightFolder[Int, HNil, L[HNil], applicativeFolder.type, L[HNil]]
// sic! this is what `z` needs
implicit val y = RightFolder.hlistRightFolder[Int, Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: HNil]]
val z = RightFolder.hlistRightFolder[Int, Int :: Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: Int :: HNil]]
// works:
case class L[O](r: Rule[JsValue, O]) extends AnyVal
implicit val lApplicative: Applicative[L] = ... // delegate to Rule.applicativeRule[JsValue]
val x = RightFolder.hlistRightFolder[Int, HNil, L[HNil], applicativeFolder.type, L[HNil]]
val y = RightFolder.hlistRightFolder[Int, Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: HNil]]
val z = RightFolder.hlistRightFolder[Int, Int :: Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: Int :: HNil]]
@stanch
Copy link
Author

stanch commented Feb 19, 2014

Somewhere in -Xlog-implicits (packages elided):

applicativeFolder.casePure is not a valid implicit value for poly.Case2[applicativeFolder.type,Int,Rule[JsValue,::[Int,HNil]]] because:
[info] hasMatchingSymbol reported error: polymorphic expression cannot be instantiated to expected type;
[info]  found   : [A, B <: HList, F[_]]applicativeFolder.Case[A,F[B]]{type Result = F[::[A,B]]}
[info]  required: poly.Case2[applicativeFolder.type,Int,Rule[JsValue,::[Int,HNil]]]
[info]     (which expands to)  poly.Case[applicativeFolder.type,::[Int,::[Rule[JsValue,::[Int,HNil]],HNil]]]
[info]   val z = RightFolder.hlistRightFolder[Int, Int :: Int :: HNil, L[HNil], applicativeFolder.type, L[Int :: Int :: HNil]]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment