Skip to content

Instantly share code, notes, and snippets.

@Rogach
Last active December 11, 2015 04:39
Show Gist options
  • Save Rogach/4546667 to your computer and use it in GitHub Desktop.
Save Rogach/4546667 to your computer and use it in GitHub Desktop.
Applying a list of functions to a case class
object ZipApply {
import shapeless._
import HList._
import Monoid._
implicit def ccMonoid[C, L <: HList](implicit iso : Iso[C, L], ml : Monoid[L]) = new Monoid[C] {
def zero = iso.from(ml.zero)
def append(a : C, b : C) = iso.from(iso.to(a) |+| iso.to(b))
}
case class Foo(i: Int, s: String, d: Double)
implicit val fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)
val handleInt = (a:Int) => "int"
val handleString = (a:String) => "string"
val handleDouble = (a:Double) => "double"
val handlers = handleInt :: handleString :: handleDouble :: HNil
handlers.zipApply(fooIso.to(Foo(1,"foo",1.0))).toList == List("int", "string", "double")
trait Monoid[T] {
def zero : T
def append(a : T, b : T) : T
}
object Monoid {
import shapeless._
import HList._
def mzero[T](implicit mt : Monoid[T]) = mt.zero
trait MonoidOps[T] {
def |+|(b : T) : T
}
implicit def monoidOps[T](a : T)(implicit mt : Monoid[T]) : MonoidOps[T] = new MonoidOps[T] {
def |+|(b : T) = mt.append(a, b)
}
implicit def booleanMonoid : Monoid[Boolean] = new Monoid[Boolean] {
def zero = false
def append(a : Boolean, b : Boolean) = a || b
}
implicit def intMonoid : Monoid[Int] = new Monoid[Int] {
def zero = 0
def append(a : Int, b : Int) = a+b
}
implicit def doubleMonoid : Monoid[Double] = new Monoid[Double] {
def zero = 0.0
def append(a : Double, b : Double) = a+b
}
implicit def stringMonoid : Monoid[String] = new Monoid[String] {
def zero = ""
def append(a : String, b : String) = a+b
}
implicit def hnilMonoid : Monoid[HNil] = new Monoid[HNil] {
def zero = HNil
def append(a : HNil, b : HNil) = HNil
}
implicit def hlistMonoid[H, T <: HList](implicit mh : Monoid[H], mt : Monoid[T]) : Monoid[H :: T] = new Monoid[H :: T] {
def zero = mh.zero :: mt.zero
def append(a : H :: T, b : H :: T) = (a.head |+| b.head) :: (a.tail |+| b.tail)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment