Concat_via_type_classes
trait HList
case class HCons[H, T <: HList](head: H, tail: T) extends HList
case object HNil extends HList
type HNil = HNil.type
// type class
trait Concat[L1 <: HList, L2 <: HList] {
type Out <: HList
def apply(l1: L1, l2: L2): Out
}
object Concat {
type Aux[L1 <: HList, L2 <: HList, Out0 <: HList] = Concat[L1, L2] { type Out = Out0 }
def apply[L1 <: HList, L2 <: HList, Out0 <: HList](f: (L1, L2) => Out0): Aux[L1, L2, Out0] = new Concat[L1, L2] {
override type Out = Out0
override def apply(l1: L1, l2: L2): Out = f(l1, l2)
}
implicit def hNilConcat[L <: HList]: Aux[HNil, L, L] = Concat((_, l) => l)
implicit def hConsConcat[H, T <: HList, L <: HList, T_concatL <: HList](implicit
concat: Aux[T, L, T_concatL]): Aux[HCons[H, T], L, HCons[H, T_concatL]] =
Concat { case (HCons(h, t), l) => HCons(h, concat(t, l)) }
object op {
implicit class ConcatOp[L1 <: HList](l1: L1) {
def concat[L2 <: HList](l2: L2)(implicit concat: Concat[L1, L2]): concat.Out = concat(l1, l2)
}
}
}
import Concat.op._
HCons(1, HCons("a", HCons(true, HNil))).concat(HCons(1L, HCons(1.0, HNil)))
Concat_via_type_projections
trait HList {
type Concat[L <: HList] <: HList
def concat[L <: HList](l: L): Concat[L]
}
case class HCons[H, T <: HList](head: H, tail: T) extends HList {
override type Concat[L <: HList] = HCons[H, T#Concat[L]]
override def concat[L <: HList](l: L): Concat[L] = HCons(head, tail.concat(l))
}
case object HNil extends HList {
override type Concat[L <: HList] = L
override def concat[L <: HList](l: L): Concat[L] = l
}
type HNil = HNil.type
HCons(1, HCons("a", HCons(true, HNil))).concat(HCons(1L, HCons(1.0, HNil)))
HList
trait HList
case class HCons[H, T <: HList](head: H, tail: T) extends HList
case object HNil extends HList
type HNil = HNil.type
HCons(1, HCons("a", HCons(true, HNil))) : HCons[Int, HCons[String, HCons[Boolean, HNil]]]
Comments
0 B
|👍
/👎
0 B
|👍
/👎