Skip to content

Commit

Permalink
simplified HList, courtesy of @kubukoz
Browse files Browse the repository at this point in the history
  • Loading branch information
gvolpe committed May 4, 2020
1 parent 6ebf658 commit a4898c4
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 44 deletions.
46 changes: 4 additions & 42 deletions modules/core/src/main/scala/dev/profunktor/redis4cats/hlist.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ object hlist {
type HNil = HNil.type

sealed trait HList {
type Prepend[A] <: HList
def ::[A](a: A): Prepend[A]
def ::[A](a: A): HCons[A, this.type] = HCons(a, this)

def reverse: HList = {
@tailrec
Expand All @@ -43,15 +42,8 @@ object hlist {
}
}

case class HCons[H, Tail <: HList](head: H, tail: Tail) extends HList {
override type Prepend[A] = HCons[A, HCons[H, Tail]]
override def ::[A](a: A): Prepend[A] = HCons(a, this)
}

case object HNil extends HList {
override type Prepend[A] = HCons[A, HNil]
override def ::[A](a: A): Prepend[A] = HCons(a, this)
}
case class HCons[+H, +Tail <: HList](head: H, tail: Tail) extends HList
case object HNil extends HList

/**
* It witnesses a relationship between two HLists.
Expand Down Expand Up @@ -83,38 +75,8 @@ object hlist {
new Witness[HCons[F[A], T]] { type R = HCons[A, w.R] }
}

/**
* Below is the `unapply` machinery to deconstruct HLists, useful for
* mattern matching while eliminating the HNil value.
*
* Slightly adapted from Miles Sabin's code posted on SO.
*
* Source: https://stackoverflow.com/questions/18468606/extractor-for-a-shapeless-hlist-that-mimics-parser-concatenation
*/
trait UnapplyRight[L <: HList] {
type Out
def apply(l: L): Out
}

trait LPUnapplyRight {
type Aux[L <: HList, Out0] = UnapplyRight[L] { type Out = Out0 }
implicit def unapplyHCons[H, T <: HList]: Aux[H :: T, Option[(H, T)]] =
new UnapplyRight[H :: T] {
type Out = Option[(H, T)]
def apply(l: H :: T): Out = Option((l.head, l.tail))
}
}

object UnapplyRight extends LPUnapplyRight {
implicit def unapplyPair[H1, H2]: Aux[H1 :: H2 :: HNil, Option[(H1, H2)]] =
new UnapplyRight[H1 :: H2 :: HNil] {
type Out = Option[(H1, H2)]
def apply(l: H1 :: H2 :: HNil): Out = Option((l.head, l.tail.head))
}
}

object ~: {
def unapply[L <: HList, Out <: Option[Any]](l: L)(implicit ua: UnapplyRight.Aux[L, Out]): Out = ua(l)
def unapply[H, T <: HList](l: H :: T): Some[(H, T)] = Some((l.head, l.tail))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class HListSpec extends AnyFunSuite with Matchers {
test("Unapply HLists (deconstruct)") {
val hl = () :: "hi" :: 123 :: true :: 's' :: 55 :: HNil

val u ~: s ~: n1 ~: b ~: c ~: n2 = hl
val u ~: s ~: n1 ~: b ~: c ~: n2 ~: HNil = hl

assert(u.isInstanceOf[Unit])
assert(s.isInstanceOf[String])
Expand Down
2 changes: 1 addition & 1 deletion site/docs/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ commandsApi.use { cmd => // RedisCommands[IO, String, String]
// Unit :: Option[String] :: Unit :: HNil
val setters =
tx.exec(commands).flatMap {
case _ ~: res1 ~: _ =>
case _ ~: res1 ~: _ ~: HNil =>
putStrLn(s"Key1 result: $res1")
}

Expand Down

0 comments on commit a4898c4

Please sign in to comment.