Skip to content

Instantly share code, notes, and snippets.

@BenFradet
Last active June 6, 2017 09:44
Show Gist options
  • Save BenFradet/e1274641d527aa144da9addebaa70478 to your computer and use it in GitHub Desktop.
Save BenFradet/e1274641d527aa144da9addebaa70478 to your computer and use it in GitHub Desktop.
Ambiguous implicits
abstract class DT
case object NullT extends DT
case object IntegerT extends DT
case object StringT extends DT
case class ST(fields: List[(String, DT)]) extends DT
sealed trait DTEncoder[A] {
def encode: DT
}
sealed trait STEncoder[A] extends DTEncoder[A] {
def encode: ST
}
object STEncoder {
def apply[A](implicit enc: STEncoder[A]): STEncoder[A] = enc
def pureST[A](st: ST): STEncoder[A] =
new STEncoder[A] { def encode: ST = st }
def pureDT[A](dt: DT): DTEncoder[A] =
new DTEncoder[A] { def encode: DT = dt }
implicit val nullEncoder: DTEncoder[Unit] = pureDT(NullT)
implicit val intEncoder: DTEncoder[Int] = pureDT(IntegerT)
implicit val stringEncoder: DTEncoder[String] = pureDT(StringT)
implicit val hnilEncoder: STEncoder[HNil] = pureST(ST(Nil))
implicit def hconsEncoder[K <: Symbol, H, T <: HList](
implicit
witness: Witness.Aux[K],
hEncoder: Lazy[DTEncoder[H]],
tEncoder: STEncoder[T]
): STEncoder[FieldType[K, H] :: T] = {
val fieldName = witness.value.name
pureST {
val head = hEncoder.value.encode
val tail = tEncoder.encode
ST((fieldName, head) +: tail.fields)
}
}
implicit def genericEncoder[A, H <: HList](
implicit
generic: LabelledGeneric.Aux[A, H],
hEncoder: Lazy[STEncoder[H]]
): STEncoder[A] =
pureST(hEncoder.value.encode)
}
case class Foo(a: Unit)
STEncoder[Foo].encode
// [error] both value nullEncoder in object STEncoder of type => DTEncoder[Unit]
// [error] and method genericEncoder in object STEncoder of type [A, H <: shapeless.HList](implicit generic: shapeless.LabelledGeneric.Aux[A,H], implicit hEncoder: shapeless.Lazy[STEncoder[H]])STEncoder[A]
// [error] match expected type ste.DTEncoder[Unit]
// [error] STEncoder[A].encode shouldBe ST(("a", NullType) :: Nil)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment