Last active
August 29, 2015 14:13
-
-
Save atamborrino/cf963eca8a10c3cb58b7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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