Skip to content

Instantly share code, notes, and snippets.

@pomadchin
Last active December 29, 2015 06:19
Show Gist options
  • Save pomadchin/7628073 to your computer and use it in GitHub Desktop.
Save pomadchin/7628073 to your computer and use it in GitHub Desktop.
shapeless custom type filter for functions
/**
* Type class supporting access to the all elements of this `HList` for functions from type `U` ~(`U => V`).
*
* author of original HList Filter Alois Cochard
*
* @author Grigory Pomadchin
*/
object am3 {
trait FuncFilter[L <: HList, U] extends DepFn1[L] { type Out <: HList }
object FuncFilter {
def apply[L <: HList, U](implicit filter: FuncFilter[L, U]): Aux[L, U, filter.Out] = filter
type Aux[L <: HList, U, Out0 <: HList] = FuncFilter[L, U] { type Out = Out0 }
implicit def nil[L <: HList, U]: Aux[HNil, U, HNil] =
new FuncFilter[HNil, U] {
type Out = HNil
def apply(l : HNil): Out = HNil
}
implicit def pick[F, T, L <: HList, U]
(implicit f : FuncFilter[L, U], e : U =:= F): Aux[(F => T) :: L, U, (F => T) :: f.Out] =
new FuncFilter[(F => T) :: L, U] {
type Out = (F => T) :: f.Out
def apply(l : (F => T) :: L) : Out = l.head :: f(l.tail)
}
implicit def drop[F, T, L <: HList, U]
(implicit f : FuncFilter[L, U], e : U =:!= F): Aux[(F => T) :: L, U, f.Out] =
new FuncFilter[(F => T) :: L, U] {
type Out = f.Out
def apply(l : (F => T) :: L): Out = f(l.tail)
}
}
}
import am3._
object mapFilter extends Poly1 {
implicit def default[F, T, L <: HList](implicit f: FuncFilter[L, F]) =
at[(F => T, L)] { case (_, l) => f(l) }
}
// usage example
// S => A, S => C, ... , etc
val cList =
S.sToA _ ::
S.sToC _ ::
A.aToB _ ::
B.bToD _ ::
D.dToC _ :: HNil
cList zip(cList mapConst cList) map mapFilter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment