Skip to content

Instantly share code, notes, and snippets.

@atamborrino
Last active August 29, 2015 14:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atamborrino/cf963eca8a10c3cb58b7 to your computer and use it in GitHub Desktop.
Save atamborrino/cf963eca8a10c3cb58b7 to your computer and use it in GitHub Desktop.
// We define a logical rule Augmentable that transform Int -> Long and Float -> Double
// at the type level with a dependent type.
// Then we want to abstract over arity and ensure that an "augment" transformation
// is defined for every type of a HList.
import shapeless._
// Dependent type T -> S (S depends on T)
trait Augmentable[T] {
type S
def augment(t: T): S
}
object Augmentable {
type Aux[T, S0] = Augmentable[T] { type S = S0 } // trick to return dependent type Augmentable[T]#S
implicit val fooInt = new Augmentable[Int] {
type S = Long
def augment(t: Int) = t.toLong
}
implicit val fooFloat = new Augmentable[Float] {
type S = Double
def augment(t: Float) = t.toDouble
}
implicit val augHNil = new Augmentable[HNil] {
type S = HNil
def augment(t: HNil) = HNil
}
implicit val augHNiltype = new Augmentable[HNil.type] {
type S = HNil.type
def augment(t: HNil.type) = HNil
}
implicit def augHList[H, S0, T <: HList, TS <: HList]
(implicit augHeadAux: Augmentable.Aux[H, S0], augTailAux: Augmentable.Aux[T, TS])
: Augmentable.Aux[H :: T, S0 :: TS] = {
new Augmentable[H :: T] {
type S = S0 :: TS
def augment(t: H :: T) = augHeadAux.augment(t.head) :: augTailAux.augment(t.tail)
}
}
}
// Testing
def bigger[T](t: T)(implicit out: Augmentable[T]): out.S = out.augment(t)
val long = bigger(32) // Dependent type Int -> Long
val double = bigger(3.0f) // Dependent type Float -> Double
// val str = bigger("foo") // does not compile
def biggerHList[HT <: HList](list: HT)(implicit augHList: Augmentable[HT]): augHList.S =
augHList.augment(list)
val bigger = biggerHList(34 :: 3.0f :: HNil) // Long :: Double :: HNil
// val biggerStr = biggerHList(34 :: "string" :: HNil) // does not compile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment