Skip to content

Instantly share code, notes, and snippets.

@hmrclt
Created May 18, 2017 16:21
Show Gist options
  • Save hmrclt/eb9941d3b62e9df18e62979748b1abe5 to your computer and use it in GitHub Desktop.
Save hmrclt/eb9941d3b62e9df18e62979748b1abe5 to your computer and use it in GitHub Desktop.
shapeless automatic case class instances
package zero {
trait Zero[A] {
def zero: Option[A]
def zeroN(s: String): Option[A] = zero
}
object Zero {
def apply[A](implicit e: Zero[A]): Zero[A] = e
def instance[A](z: Option[A]): Zero[A] = new Zero[A] {
val zero = z
}
def instance[A](z: Option[A], v: String => Option[A]): Zero[A] = new Zero[A] {
val zero = z
override def zeroN(s:String) = v(s)
}
// 'basic' types
implicit val zeroInt = instance(Some(0), x => Some(x.size))
implicit val zeroString = instance(Some(""), x => Some(x))
implicit val zeroOption = instance(Some(None))
implicit val zeroBoolean = instance(Some(false), x => Some(x.size % 2 == 0))
implicit val zeroList = instance(Some(Nil))
// HLists
implicit val zeroHNil: Zero[HNil] = instance(Some(HNil))
implicit def zeroHList[S <: Symbol, H, T <: HList](
implicit
witness: Witness.Aux[S],
zeroHead: Lazy[Zero[H]],
zeroTail: Zero[T]
): Zero[FieldType[S,H] :: T] = {
val fieldname = witness.value.name
instance {
for {
h <- zeroHead.value.zeroN(fieldname)
t <- zeroTail.zero
} yield {
field[S](h) :: t
}
}
}
// generic
implicit def zeroGeneric[A, R <: HList](
implicit gen: LabelledGeneric.Aux[A, R],
enc: Lazy[Zero[R]]
): Zero[A] = instance{enc.value.zero.map{gen.from}}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment