Skip to content

Instantly share code, notes, and snippets.

@pomadchin
Last active November 5, 2015 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pomadchin/bf46e21cb180c2a81664 to your computer and use it in GitHub Desktop.
Save pomadchin/bf46e21cb180c2a81664 to your computer and use it in GitHub Desktop.
Implement product type in Scala with generic update function working on its parts
// Stackoverflow discussion: http://stackoverflow.com/questions/33541107/implement-product-type-in-scala-with-generic-update-function-working-on-its-part
// shapeless 2.2.5
import shapeless._
import ops.hlist._
import ops.traversable._
import shapeless.syntax.std._
import shapeless.syntax.std.traversable._
case class A(fieldA: String)
case class B(fieldB: Int)
case class C(fieldC: Double)
case class D()
val list = A("default") :: B(0) :: C(0d) :: HNil
def caseclassA (a: A) = a.copy(fieldA = "caseclassA")
def caseclassB (b: B) = b.copy(fieldB = 1)
def caseclassC (c: C) = c.copy(fieldC = 1d)
// we can define a Poly function to apply it to HList
trait lowPriority extends Poly1 {
implicit def default[T] = at[T](poly.identity)
}
object polyApplyToTypeCompose extends lowPriority {
implicit def caseA = at[A](caseclassA(_))
implicit def caseB = at[B](caseclassB(_))
implicit def caseC = at[C](caseclassC(_))
}
object polyApplyToTypeA extends lowPriority {
implicit def caseA = at[A](caseclassA(_))
}
object polyApplyToTypeB extends lowPriority {
implicit def caseB = at[B](caseclassB(_))
}
object polyApplyToTypeC extends lowPriority {
implicit def caseC = at[C](caseclassC(_))
}
list.map(polyApplyToTypeC) //> applies only to type C
// or we can define more complex function without defining poly functions
def applyToType[L <: HList, P <: HList, PO <: HList, S <: HList, F]
(fun: F => F, l: L)
(implicit partition: Partition.Aux[L, F, P, S],
tt: ToTraversable.Aux[P, List, F],
ft: FromTraversable[P],
p: Prepend.Aux[S, P, PO],
a: Align[PO, L]): L = (l.filterNot[F] ::: l.filter[F].toList[F].map(fun).toHList[P].get).align[L]
applyToType(caseclassA, list)
//> res0: shapeless.::[A,shapeless.::[B,shapeless.::[C,shapeless.HNil]]] = A(caseclassA) :: B(0) :: C(0.0) :: HNil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment