Skip to content

Instantly share code, notes, and snippets.

@ceedubs
Created March 5, 2016 21:45
Show Gist options
  • Save ceedubs/37e351b5d8a80f4c5e68 to your computer and use it in GitHub Desktop.
Save ceedubs/37e351b5d8a80f4c5e68 to your computer and use it in GitHub Desktop.
The start of an HList implementation from my nescala unconf session. There are two errors that are left to the reader as an exercise. Hint: it's mostly right but a couple types are incorrect.
import HList._
sealed abstract class HList
case object HNil extends HList
final case class HCons[H, T <: HList](head: H, tail: T) extends HList
object HList {
type HNil = HNil.type
type ::[H, T <: HList] = HCons[H, T]
implicit final class HListOps[L <: HList](l: L) {
def filterNot[A](implicit f: FilterNot[A, L]): f.Out =
f(l)
}
}
trait FilterNot[A, L <: HList] {
type Out <: HList
def apply(l: L): Out
}
object FilterNot extends LowPriorityFilterNotInstances {
implicit def filterNotHNil[A]: Aux[A, HNil, HNil] = new FilterNot[A, HNil] {
type Out = HNil
def apply(l: HNil): HNil = HNil
}
implicit def filterNotIsType[A, H <: A, T <: HList](implicit f: FilterNot[A, T]): Aux[A, H :: T, f.Out] = new FilterNot[A, H :: f.Out] {
type Out = f.Out
def apply(l: H :: T): f.Out = f(l.tail)
}
}
trait LowPriorityFilterNotInstances {
type Aux[A, L <: HList, O <: HList] = FilterNot[A, L]{ type Out = O }
implicit def filterNotIsntType[A, H, T <: HList](implicit f: FilterNot[A, T]): Aux[A, H :: T, H :: f.Out] = new FilterNot[A, H :: f.Out] {
type Out = H :: f.Out
def apply(l: H :: T): H :: f.Out = HCons(l.head, f(l.tail))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment