Skip to content

Instantly share code, notes, and snippets.

@pulasthibandara
Created April 27, 2020 20:26
Show Gist options
  • Save pulasthibandara/dab307cb23e93aacba9f746765537895 to your computer and use it in GitHub Desktop.
Save pulasthibandara/dab307cb23e93aacba9f746765537895 to your computer and use it in GitHub Desktop.
Scala HList strip suffix
import shapeless.{ ::, DepFn2, HList, HNil }
import scala.annotation.implicitNotFound
/**
* Returns {Out = B} after stripping suffix {A} from {BA}
* {{{
* val a: Int :: String :: HNil 1 :: "a" :: HNil
* val ba: Boolean :: String :: Int :: String :: HNil = true :: "b" :: 1 :: "a" :: HNil
* val b: Boolean :: String :: HNil = StripSuffix[Int :: String :: HNil, Boolean :: String :: Int :: String :: HNil](a, ba)
* }}}
*/
@implicitNotFound("Cannot find suffix ${A} in ${BA}")
trait StripSuffix[A <: HList, BA <: HList] extends DepFn2[A, BA] {
type Out <: HList
}
object StripSuffix {
type Aux[A <: HList, BA <: HList, B <: HList] = StripSuffix[A, BA] {
type Out = B
}
implicit def equalCase[BA <: HList]: Aux[BA, BA, HNil] = new StripSuffix[BA, BA] {
type Out = HNil
def apply(a: BA, ba: BA): Out = HNil
}
implicit def hlistCase[A <: HList, BH, BT <: HList, BtOut <: HList](
implicit up: StripSuffix.Aux[A, BT, BtOut]
): StripSuffix.Aux[A, BH :: BT, BH :: BtOut] = new StripSuffix[A, BH :: BT] {
type Out = BH :: BtOut
def apply(a: A, ba: BH :: BT) =
ba.head :: up.apply(a, ba.tail)
}
def apply[A <: HList, BA <: HList](
implicit stripSuffix: StripSuffix[A, BA]
): StripSuffix.Aux[A, BA, stripSuffix.Out] = stripSuffix
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment