Skip to content

Instantly share code, notes, and snippets.

@nightscape
Created December 9, 2016 10:52
Show Gist options
  • Save nightscape/3e1efabd5c6d92fff0195cdd8b8a5267 to your computer and use it in GitHub Desktop.
Save nightscape/3e1efabd5c6d92fff0195cdd8b8a5267 to your computer and use it in GitHub Desktop.
package shiplis
import shapeless._, poly._, ops.hlist._
object MapWith
{
object Apply
extends Poly2
{
implicit def c[A, B, R, Tail <: HList, F <: Poly2]
(implicit cse: poly.Case2.Aux[F, A, B, R])
: Case2.Aux[this.type, B, ((A, F), Tail), ((A, F), R :: Tail)] =
at[B, ((A, F), Tail)] {
case (b, ((a, f), z)) =>
(a, f) -> ((cse(a, b)) :: z)
}
}
}
final class MapWithSyntax[L <: HList](self: L)
{
def mapWith[A, F <: Poly2, R](f: F, a: A)
(implicit folder:
RightFolder.Aux[L, ((A, F), HNil), MapWith.Apply.type, ((A, F), R)]) =
folder(self, ((a, f), HNil: HNil))._2
}
trait ToMapWithSyntax
{
implicit def ToMapWithSyntax[A <: HList](a: A) =
new MapWithSyntax(a)
}
object map1
extends Poly2
{
implicit def cse[L <: HList, F <: Poly1, R <: HList]
(implicit mapper: Mapper.Aux[F, L, R]) =
at[L, F] {
case (l, _) => mapper(l)
}
}
object f1
extends Poly2
{
implicit def cse = at[(Int, Int), Int] {
case ((b, c), a) => a * b + c
}
}
object f2
extends Poly1
{
implicit def cse = at[Int](a => s"1: $a")
}
object f3
extends Poly1
{
implicit def cse = at[Int](a => a * 20)
}
class MapWithSpec
extends org.specs2.Specification
with ToMapWithSyntax
{
def is = s2"""
apply a Poly with additional fixed args to a HList $argmap
apply a HList of Polys to each element of another HList $funmap
"""
def argmap = {
val h = 1 :: 2 :: 3 :: HNil
h.mapWith(f1, (5, 4)) must_== 9 :: 14 :: 19 :: HNil
}
def funmap = {
val h = 1 :: 2 :: 3 :: HNil
val funs = f3 :: f2 :: f3 :: HNil
val r = funs.mapWith(map1, h)
val l1 = 20 :: 40 :: 60 :: HNil
val l2 = "1: 1" :: "1: 2" :: "1: 3" :: HNil
r must_== l1 :: l2 :: l1 :: HNil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment