Skip to content

Instantly share code, notes, and snippets.

@fehu
Created November 17, 2017 04:33
Show Gist options
  • Save fehu/ace5d384e07d5600cce9f4f3bdb5b73f to your computer and use it in GitHub Desktop.
Save fehu/ace5d384e07d5600cce9f4f3bdb5b73f to your computer and use it in GitHub Desktop.
Scala - shapeless - CovUnliftFilter
import scala.language.higherKinds
import shapeless._
import shapeless.ops.hlist.IsHCons
/**
* Type class supporting access to all the elements of this `HList`, that are lifted sub-types of `U`.
* Selects all {{{ F[A] }}}, contained in the list `L`, such that {{{ A <: U }}}.
*/
trait CovUnliftFilter[L <: HList, F[_], U] extends DepFn1[L] with Serializable { type Out <: HList }
object CovUnliftFilter {
def apply[L <: HList, F[_], U](implicit filter: CovUnliftFilter[L, F, U]): Aux[L, F, U, filter.Out] = filter
type Aux[L <: HList, F[_], U, Out0 <: HList] = CovUnliftFilter[L, F, U] { type Out = Out0 }
implicit def take[L <: HList, F[_], U, FH, H, T <: HList](
implicit
cons: IsHCons.Aux[L, FH, T], ev0: FH <:< F[H], ev: H <:< U, next: CovUnliftFilter[T, F, U]
): CovUnliftFilter[L, F, U] = new CovUnliftFilter[L, F, U]{
type Out = FH :: next.Out
def apply(t: L): FH :: next.Out = cons.head(t) :: next(cons.tail(t))
}
implicit def drop[L <: HList, F[_], U, FH, H, T <: HList](
implicit
cons: IsHCons.Aux[L, FH, T], ev0: FH <:< F[H], ev: H <:!< U, next: CovUnliftFilter[T, F, U]
): CovUnliftFilter[L, F, U] = new CovUnliftFilter[L, F, U]{
type Out = next.Out
def apply(t: L): next.Out = next(cons.tail(t))
}
implicit def nil[F[_], U]: CovUnliftFilter[HNil, F, U] = Nil.asInstanceOf[CovUnliftFilter[HNil, F, U]]
private object Nil extends CovUnliftFilter[HNil, Id, Any]{
type Out = HNil
def apply(t: HNil): HNil = HNil
}
}
/**
* Type class witnessing that `L` contains at least one element, satisfying corresponding filter conditions.
*/
trait CovUnliftFilteredNonempty[L <: HList, F[_], U]
object CovUnliftFilteredNonempty{
implicit def evidence[L <: HList, F[_], U, L0 <: HList](
implicit
filter: CovUnliftFilter.Aux[L, F, U, L0], cons: IsHCons[L0]
): CovUnliftFilteredNonempty[L, F, U] = Evidence.asInstanceOf[CovUnliftFilteredNonempty[L, F, U]]
private object Evidence extends CovUnliftFilteredNonempty[HList, Id, Any]
}
import scala.language.higherKinds
import shapeless.{HList, Id}
import shapeless.ops.hlist.LiftAll
package object hlist {
/** Alias for [[CovUnliftFilter]] when `HList`'s elements are not lifted. */
type CovFilter[L <: HList, U] = CovUnliftFilter[L, Id, U]
object CovFilter {
def apply[L <: HList, U](implicit filter: CovFilter[L, U]): Aux[L, U, filter.Out] = filter
type Aux[L <: HList, U, Out0 <: HList] = CovFilter[L, U] {type Out = Out0}
}
/** Alias for [[CovUnliftFilteredNonempty]] when `HList`'s elements are not lifted. */
type CovFilteredNonempty[L <: HList, U] = CovUnliftFilteredNonempty[L, Id, U]
/** An alias for [[LiftAll]] `apply`, that preserves type refinement of lifted instances. */
object LiftAllInstances{
def apply[F[_], In <: HList](implicit ev: LiftAll[F, In]): ev.Out = ev.instances
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment