Created
March 3, 2017 07:15
-
-
Save Atry/34282e9784a83b275ac7b91d2ff36a9b to your computer and use it in GitHub Desktop.
A universal type class that includes all shapeless.HList operations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shapeless._ | |
import shapeless.ops.hlist.ZipWithIndex.Helper | |
import shapeless.poly._ | |
import shapeless.ops.hlist.{ | |
Length, | |
LiftAll, | |
Mapper, | |
ToCoproduct, | |
ToList, | |
ZipWithIndex | |
} | |
/** | |
* @author 杨博 (Yang Bo) <[email protected]> | |
*/ | |
trait HListWitness[L <: HList] { | |
type N <: Nat | |
def length: Length.Aux[L, N] | |
def toCoproduct: ToCoproduct[L] | |
def zipWithIndexHelper[Start <: Nat]: ZipWithIndex.Helper[L, Start] | |
def zipWithIndex: ZipWithIndex[L] | |
// def liftAll[F[_]]: LiftAll[F, L] | |
type Cases[HF <: Poly] <: HList | |
def map[HF <: Poly](cases: Cases[HF]): Mapper[HF, L] | |
def map[HF <: Poly]( | |
implicit liftAll: LiftAll.Aux[Case1[HF, ?], L, Cases[HF]]) | |
: Mapper[HF, L] = { | |
this.map[HF](liftAll.instances) | |
} | |
} | |
object HListWitness { | |
implicit object HNilWitness extends HListWitness[HNil] { | |
override def length = Length.hnilLength | |
override type N = _0 | |
override def toCoproduct: ToCoproduct[HNil] = implicitly | |
override def zipWithIndexHelper[Start <: Nat] = Helper.hnil[Start] | |
override def zipWithIndex = ZipWithIndex.default(zipWithIndexHelper) | |
type Cases[HF <: Poly] = HNil | |
type MapResult[HF <: Poly, C <: Cases[HF]] = HNil | |
override def map[HF <: Poly](cases: Cases[HF]) = Mapper.hnilMapper1[HF] | |
} | |
trait HConsWitness[H, T <: HList] extends HListWitness[H :: T] { | |
val tailWitness: HListWitness[T] | |
override type N = Succ[tailWitness.N] | |
// OK | |
override def length = { | |
Length.hlistLength[H, T, tailWitness.N](tailWitness.length, implicitly) | |
} | |
// Can be type safe | |
override def toCoproduct: ToCoproduct[H :: T] = { | |
ToCoproduct.hlistToCoproduct(tailWitness.toCoproduct) | |
} | |
override def zipWithIndexHelper[Start <: Nat] = { | |
val tailHelper = tailWitness.zipWithIndexHelper[Succ[Start]] | |
Helper.hcons[H, T, tailHelper.Out, Start](tailHelper) | |
} | |
override def zipWithIndex = ZipWithIndex.default(zipWithIndexHelper) | |
override type Cases[HF <: Poly] = Case1[HF, H] :: tailWitness.Cases[HF] | |
// Require recursive typeof expression to be type safe, which is not support in Scala | |
override def map[HF <: Poly](cases: Cases[HF]) = { | |
Mapper.hlistMapper1[HF, H, T](cases.head, tailWitness.map(cases.tail)) | |
} | |
} | |
implicit def hconWitness[H, T <: HList]( | |
tailWitness0: HListWitness[T]): HConsWitness[H, T] { | |
val tailWitness: tailWitness0.type | |
} = { | |
new { | |
override val tailWitness: tailWitness0.type = tailWitness0 | |
} with HConsWitness[H, T] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment